1Cheat sheet 2=========== 3 4.. currentmodule:: websockets 5 6Server 7------ 8 9* Write a coroutine that handles a single connection. It receives a WebSocket 10 protocol instance and the URI path in argument. 11 12 * Call :meth:`~protocol.WebSocketCommonProtocol.recv` and 13 :meth:`~protocol.WebSocketCommonProtocol.send` to receive and send 14 messages at any time. 15 16 * When :meth:`~protocol.WebSocketCommonProtocol.recv` or 17 :meth:`~protocol.WebSocketCommonProtocol.send` raises 18 :exc:`~exceptions.ConnectionClosed`, clean up and exit. If you started 19 other :class:`asyncio.Task`, terminate them before exiting. 20 21 * If you aren't awaiting :meth:`~protocol.WebSocketCommonProtocol.recv`, 22 consider awaiting :meth:`~protocol.WebSocketCommonProtocol.wait_closed` 23 to detect quickly when the connection is closed. 24 25 * You may :meth:`~protocol.WebSocketCommonProtocol.ping` or 26 :meth:`~protocol.WebSocketCommonProtocol.pong` if you wish but it isn't 27 needed in general. 28 29* Create a server with :func:`~server.serve` which is similar to asyncio's 30 :meth:`~asyncio.AbstractEventLoop.create_server`. You can also use it as an 31 asynchronous context manager. 32 33 * The server takes care of establishing connections, then lets the handler 34 execute the application logic, and finally closes the connection after the 35 handler exits normally or with an exception. 36 37 * For advanced customization, you may subclass 38 :class:`~server.WebSocketServerProtocol` and pass either this subclass or 39 a factory function as the ``create_protocol`` argument. 40 41Client 42------ 43 44* Create a client with :func:`~client.connect` which is similar to asyncio's 45 :meth:`~asyncio.BaseEventLoop.create_connection`. You can also use it as an 46 asynchronous context manager. 47 48 * For advanced customization, you may subclass 49 :class:`~server.WebSocketClientProtocol` and pass either this subclass or 50 a factory function as the ``create_protocol`` argument. 51 52* Call :meth:`~protocol.WebSocketCommonProtocol.recv` and 53 :meth:`~protocol.WebSocketCommonProtocol.send` to receive and send messages 54 at any time. 55 56* You may :meth:`~protocol.WebSocketCommonProtocol.ping` or 57 :meth:`~protocol.WebSocketCommonProtocol.pong` if you wish but it isn't 58 needed in general. 59 60* If you aren't using :func:`~client.connect` as a context manager, call 61 :meth:`~protocol.WebSocketCommonProtocol.close` to terminate the connection. 62 63.. _debugging: 64 65Debugging 66--------- 67 68If you don't understand what ``websockets`` is doing, enable logging:: 69 70 import logging 71 logger = logging.getLogger('websockets') 72 logger.setLevel(logging.INFO) 73 logger.addHandler(logging.StreamHandler()) 74 75The logs contain: 76 77* Exceptions in the connection handler at the ``ERROR`` level 78* Exceptions in the opening or closing handshake at the ``INFO`` level 79* All frames at the ``DEBUG`` level — this can be very verbose 80 81If you're new to ``asyncio``, you will certainly encounter issues that are 82related to asynchronous programming in general rather than to ``websockets`` 83in particular. Fortunately Python's official documentation provides advice to 84`develop with asyncio`_. Check it out: it's invaluable! 85 86.. _develop with asyncio: https://docs.python.org/3/library/asyncio-dev.html 87 88Passing additional arguments to the connection handler 89------------------------------------------------------ 90 91When writing a server, if you need to pass additional arguments to the 92connection handler, you can bind them with :func:`functools.partial`:: 93 94 import asyncio 95 import functools 96 import websockets 97 98 async def handler(websocket, path, extra_argument): 99 ... 100 101 bound_handler = functools.partial(handler, extra_argument='spam') 102 start_server = websockets.serve(bound_handler, '127.0.0.1', 8765) 103 104 asyncio.get_event_loop().run_until_complete(start_server) 105 asyncio.get_event_loop().run_forever() 106 107Another way to achieve this result is to define the ``handler`` coroutine in 108a scope where the ``extra_argument`` variable exists instead of injecting it 109through an argument. 110