pythonpython-3.xwebsocket

python websockets, how to setup connect timeout


Let's say that the WebSocket server is temporary down, and it drops incoming packets (rather than rejecting them)

Currently, it takes around 95 seconds between the connection attempt and the TimeoutError

I can't seem to find a way to reduce that window (so I can try another WebSocket server)

This is the demo code that I am running: (just taken from the official docs

#!/usr/bin/env python

import asyncio
import websockets
import os
import socket
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s [%(name)s.%(funcName)s:%(lineno)d]: %(message)s', datefmt='%m-%d %H:%M:%S', )


host = os.environ.get('SERVER_URL','localhost:9090')
self_id = os.environ.get('SELF_ID',socket.gethostname())

connect_url =f'ws://{host}/{self_id}'
logging.info(f'Connect to: {connect_url}')

async def hello(uri):
    logging.info(f'Connecting to {uri}')
    async with websockets.connect(uri, timeout=1, close_timeout=1) as websocket:
        logging.info(f"Conected to {uri}")
        async for message in websocket:
            await websocket.send(message)

asyncio.get_event_loop().run_until_complete(
    hello(connect_url))

Solution

  • You can use asyncio's wait_for() like this:

    import websockets
    import asyncio
    from concurrent.futures import TimeoutError as ConnectionTimeoutError
    # whatever url is your websocket server
    url = 'ws://localhost:9090'
    # timeout in seconds
    timeout = 10  
    try:
        # make connection attempt
        connection = await asyncio.wait_for(websockets.connect(url), timeout)
    except ConnectionTimeoutError as e:
        # handle error
        print('Error connecting.')
    

    It will raise a <class 'concurrent.futures._base.TimeoutError'> exception which can be caught with the except ConnectionTimeoutError block.

    In python3.8 it raises a TimeoutError which can be caught with the except asyncio.exceptions.TimeoutError block.