blob: f897326a6ba467ef1834e982b7396892cd2ff51e [file] [log] [blame]
Cheat sheet
===========
.. currentmodule:: websockets
Server
------
* Write a coroutine that handles a single connection. It receives a WebSocket
protocol instance and the URI path in argument.
* Call :meth:`~protocol.WebSocketCommonProtocol.recv` and
:meth:`~protocol.WebSocketCommonProtocol.send` to receive and send
messages at any time.
* When :meth:`~protocol.WebSocketCommonProtocol.recv` or
:meth:`~protocol.WebSocketCommonProtocol.send` raises
:exc:`~exceptions.ConnectionClosed`, clean up and exit. If you started
other :class:`asyncio.Task`, terminate them before exiting.
* If you aren't awaiting :meth:`~protocol.WebSocketCommonProtocol.recv`,
consider awaiting :meth:`~protocol.WebSocketCommonProtocol.wait_closed`
to detect quickly when the connection is closed.
* You may :meth:`~protocol.WebSocketCommonProtocol.ping` or
:meth:`~protocol.WebSocketCommonProtocol.pong` if you wish but it isn't
needed in general.
* Create a server with :func:`~server.serve` which is similar to asyncio's
:meth:`~asyncio.AbstractEventLoop.create_server`. You can also use it as an
asynchronous context manager.
* The server takes care of establishing connections, then lets the handler
execute the application logic, and finally closes the connection after the
handler exits normally or with an exception.
* For advanced customization, you may subclass
:class:`~server.WebSocketServerProtocol` and pass either this subclass or
a factory function as the ``create_protocol`` argument.
Client
------
* Create a client with :func:`~client.connect` which is similar to asyncio's
:meth:`~asyncio.BaseEventLoop.create_connection`. You can also use it as an
asynchronous context manager.
* For advanced customization, you may subclass
:class:`~server.WebSocketClientProtocol` and pass either this subclass or
a factory function as the ``create_protocol`` argument.
* Call :meth:`~protocol.WebSocketCommonProtocol.recv` and
:meth:`~protocol.WebSocketCommonProtocol.send` to receive and send messages
at any time.
* You may :meth:`~protocol.WebSocketCommonProtocol.ping` or
:meth:`~protocol.WebSocketCommonProtocol.pong` if you wish but it isn't
needed in general.
* If you aren't using :func:`~client.connect` as a context manager, call
:meth:`~protocol.WebSocketCommonProtocol.close` to terminate the connection.
.. _debugging:
Debugging
---------
If you don't understand what ``websockets`` is doing, enable logging::
import logging
logger = logging.getLogger('websockets')
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())
The logs contain:
* Exceptions in the connection handler at the ``ERROR`` level
* Exceptions in the opening or closing handshake at the ``INFO`` level
* All frames at the ``DEBUG`` level — this can be very verbose
If you're new to ``asyncio``, you will certainly encounter issues that are
related to asynchronous programming in general rather than to ``websockets``
in particular. Fortunately Python's official documentation provides advice to
`develop with asyncio`_. Check it out: it's invaluable!
.. _develop with asyncio: https://docs.python.org/3/library/asyncio-dev.html
Passing additional arguments to the connection handler
------------------------------------------------------
When writing a server, if you need to pass additional arguments to the
connection handler, you can bind them with :func:`functools.partial`::
import asyncio
import functools
import websockets
async def handler(websocket, path, extra_argument):
...
bound_handler = functools.partial(handler, extra_argument='spam')
start_server = websockets.serve(bound_handler, '127.0.0.1', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Another way to achieve this result is to define the ``handler`` coroutine in
a scope where the ``extra_argument`` variable exists instead of injecting it
through an argument.