Cheat sheet¶
Server¶
Write a coroutine that handles a single connection. It receives a websocket protocol instance and the URI path in argument.
Create a server with
serve()
which is similar to asyncio’screate_server()
.On Python ≥ 3.5.1, 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
WebSocketServerProtocol
and pass either this subclass or a factory function as thecreate_protocol
argument.
Client¶
Create a client with
connect()
which is similar to asyncio’screate_connection()
.On Python ≥ 3.5.1, you can also use it as an asynchronous context manager.
For advanced customization, you may subclass
WebSocketClientProtocol
and pass either this subclass or a factory function as thecreate_protocol
argument.
Call
recv()
andsend()
to receive and send messages at any time.You may
ping()
orpong()
if you wish but it isn’t needed in general.If you aren’t using
connect()
as a context manager, callclose()
to terminate the connection.
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
levelExceptions in the opening or closing handshake at the
INFO
levelAll 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!
Keeping connections open¶
Pinging the other side once in a while is a good way to check whether the connection is still working, and also to keep it open in case something kills idle connections after some time:
while True:
try:
msg = await asyncio.wait_for(ws.recv(), timeout=20)
except asyncio.TimeoutError:
# No data in 20 seconds, check the connection.
try:
pong_waiter = await ws.ping()
await asyncio.wait_for(pong_waiter, timeout=10)
except asyncio.TimeoutError:
# No response to ping in 10 seconds, disconnect.
break
else:
# do something with msg
...
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 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
corountine in
a scope where the extra_argument
variable exists instead of injecting it
through an argument.