I'm using uvloop
with websockets
as
import uvloop
coro = websockets.serve(handler, host, port) # creates new server
loop = uvloop.new_event_loop()
loop.create_task(coro)
loop.run_forever()
It works fine, I'm just wondering whether I could run to some unexpected problems without setting the global asyncio
policy to uvloop
. As far as I understand, not setting the global policy should work as long as nothing down there doesn't use the global asyncio
methods, but works with the passed-down event loop directly. Is that correct?
There are three main global objects in asyncio:
All the attempts to get the current context in asyncio go through a single function, asyncio.get_event_loop.
One thing to remember is that since Python 3.6 (and Python 3.5.3+), get_event_loop
has a specific behavior:
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
loop.run_forever()
Here the policy is the uvloop policy. The loop returned by get_event_loop
is a uvloop, and it is set as the default loop for this thread. When this loop is running, it is registered as the running loop.
In this example, calling get_event_loop()
anywhere in this thread returns the right loop.
import uvloop
loop = uvloop.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_forever()
Here the policy is still the default policy. The loop returned by new_event_loop
is a uvloop, and it is set as the default loop for this thread explicitly using asyncio.set_event_loop
. When this loop is running, it is registered as the running loop.
In this example, calling get_event_loop()
anywhere in this thread returns the right loop.
import uvloop
loop = uvloop.new_event_loop()
loop.run_forever()
Here the policy is still the default policy. The loop returned by new_event_loop
is a uvloop, but it is not set as the default loop for this thread. When this loop is running, it is registered as the running loop.
In this example, calling get_event_loop()
within a coroutine returns the right loop (the running uvloop). But calling get_event_loop()
outside a coroutine will result in a new standard asyncio loop, set as the default loop for this thread.
So the first two approaches are fine, but the third one is discouraged.