Closed kinware closed 6 years ago
Digging into the sanic I could see that there is a difference in how the loop is handled when launching sanic through Sanic.run() vs Sanic.create_server().
Sanic.run() uses
run_async=False # Implicit from default parameter of Sanic._helper()
loop=None # Implicit from default parameter of Sanic._helper()
which causes sanic.server.serve() to create a new loop by doing:
if not run_async:
# create new event_loop after fork
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
Sanic.create_server() uses
run_async=True # Explicitly set in create_server()
loop=get_event_loop() # Explicitly set in create_server()
This does not create a new loop, but it also leaves it to the caller to run the actual event loop (as opposed to Sanic.run() which conveniently does run the loop).
So there are two ways to get rid of the exceptions.
One is to just allow Sanic to create it's on loop and update the code to use that loop. Easily accomplished by changing loop.run_in_executor()
to asyncio.get_event_loop().run_in_executor()
(or possibly request.app.loop.run_in_executor()
).
The alternative is to run the event loop outside of sanic and switch from Sanic.run() to Sanic.create_server() which should correctly pick up the event loop as it uses get_event_loop() internally (instad of new_event_loop() as Sanic.app()
does).
This solves the problem for me. Maybe someone else finds this useful too.
Closing issue.
request.app.loop.run_in_executor()
request.app.loop.run_in_executor(None,func)
I'm not very good at python, can the executor be set to None and let it read the default values?
I'm trying to get Sanic (and uvloop) to use a worker pool of sub-processes for CPU intensive requests. So far I've come up with the below code. The example "work" is first run once (to ensure the process pool works as intended). Then sanic is started and the user can trigger the "work" through HTTP. See below.
I run the above using sanic from master branch, uvloop 0.8.1 together with python 3.6.3. The first run of the worker function in a subprocess (before starting sanic) works fine. However, when initiating the work through sanic (http://localhost:12000/ask) it bombs with an exception:
It appears from the exceptions that there are multiple event loops in play here, but I'm not quite sure why/where these are created. Maybe I'm misunderstanding the python event loop concept? Also not sure what happens when the current process fork()s and the child worker processes inherits the event loop from the master process.
Any ideas what I'm doing wrong here?
If I can get it working I'd be happy to submit a PR for sanic/examples/ showing how to handle CPU intensive work in a subprocess in conjunction with the normal async processing sanic does so well.