asyncio.rst (2761B)
1 Using asyncio 2 ============= 3 4 .. currentmodule:: websockets 5 6 How do I run two coroutines in parallel? 7 ---------------------------------------- 8 9 You must start two tasks, which the event loop will run concurrently. You can 10 achieve this with :func:`asyncio.gather` or :func:`asyncio.create_task`. 11 12 Keep track of the tasks and make sure they terminate or you cancel them when 13 the connection terminates. 14 15 Why does my program never receive any messages? 16 ----------------------------------------------- 17 18 Your program runs a coroutine that never yields control to the event loop. The 19 coroutine that receives messages never gets a chance to run. 20 21 Putting an ``await`` statement in a ``for`` or a ``while`` loop isn't enough 22 to yield control. Awaiting a coroutine may yield control, but there's no 23 guarantee that it will. 24 25 For example, :meth:`~legacy.protocol.WebSocketCommonProtocol.send` only yields 26 control when send buffers are full, which never happens in most practical 27 cases. 28 29 If you run a loop that contains only synchronous operations and 30 a :meth:`~legacy.protocol.WebSocketCommonProtocol.send` call, you must yield 31 control explicitly with :func:`asyncio.sleep`:: 32 33 async def producer(websocket): 34 message = generate_next_message() 35 await websocket.send(message) 36 await asyncio.sleep(0) # yield control to the event loop 37 38 :func:`asyncio.sleep` always suspends the current task, allowing other tasks 39 to run. This behavior is documented precisely because it isn't expected from 40 every coroutine. 41 42 See `issue 867`_. 43 44 .. _issue 867: https://github.com/python-websockets/websockets/issues/867 45 46 Why am I having problems with threads? 47 -------------------------------------- 48 49 If you choose websockets' default implementation based on :mod:`asyncio`, then 50 you shouldn't use threads. Indeed, choosing :mod:`asyncio` to handle concurrency 51 is mutually exclusive with :mod:`threading`. 52 53 If you believe that you need to run websockets in a thread and some logic in 54 another thread, you should run that logic in a :class:`~asyncio.Task` instead. 55 If it blocks the event loop, :meth:`~asyncio.loop.run_in_executor` will help. 56 57 This question is really about :mod:`asyncio`. Please review the advice about 58 :ref:`asyncio-multithreading` in the Python documentation. 59 60 Why does my simple program misbehave mysteriously? 61 -------------------------------------------------- 62 63 You are using :func:`time.sleep` instead of :func:`asyncio.sleep`, which 64 blocks the event loop and prevents asyncio from operating normally. 65 66 This may lead to messages getting send but not received, to connection 67 timeouts, and to unexpected results of shotgun debugging e.g. adding an 68 unnecessary call to :meth:`~legacy.protocol.WebSocketCommonProtocol.send` 69 makes the program functional.