2

To allow timeouts receiving data via Python websocket, the FAQ: How do I set a timeout on recv()? recommends using asynchronously receive data:

await asyncio.wait_for(websocket.recv(), timeout=10)

Since the function I receive data is not async, I've adapted this answer to run the asyncio loop until data was received or the timeout occurred:

loop.run_until_complete(asyncio.wait_for(ws.recv(), timeout=10))

Unfortunately this statement seems to be not valid, since the following exception occurs:

An asyncio.Future, a coroutine or an awaitable is required

For me, it looks like asyncio.wait_for is no valid parameter for the run_until_complete although the documentation clearly shows an example which awaits for it.

What am I missing here - and what would be the correct way to use asyncio.wait_for in a synchronous method?

Fruchtzwerg
  • 10,999
  • 12
  • 40
  • 49

2 Answers2

2

You need to feed loop.run_until_complete with a coroutine. To do so, you can wrap your receiving code into an async function:

async def receive_message():
    return await asyncio.wait_for(ws.recv(), timeout=10)

loop.run_until_complete(receive_message())

Here's a fully working code:

import asyncio
import websockets

URI = "ws://0.0.0.0:8765"
TIMEOUT = 2

async def create_ws():
    return await websockets.connect(URI)

async def receive_message():
    ws = await create_ws()
    print("Connected")
    message = await asyncio.wait_for(ws.recv(), timeout=TIMEOUT)
    print(f"Received message in less than {TIMEOUT} seconds: {message}")

if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(receive_message())
RobBlanchard
  • 855
  • 3
  • 17
2

There are two common websocket modules available in Python. While websockets is imported with import websockets there is also the websocket-client which is imported with import websocket.

Both of the modules offering nearly the same API where ws.recv() allows to receive data.

The fact the modules are so similar to each other may cause confusion which at least lead to my exception.

While websockets are capable of async operations, websocket is not. This means my statement

loop.run_until_complete(asyncio.wait_for(ws.recv(), timeout=10))

will only work for websockets, if used with websocket, the exception

An asyncio.Future, a coroutine or an awaitable is required

will occur.

Fruchtzwerg
  • 10,999
  • 12
  • 40
  • 49