If you attempted to start the server as usual inside Jupyter, for example:
import uvicorn
if __name__ == "__main__":
uvicorn.run(app)
you would get the following error:
RuntimeError: asyncio.run() cannot be called from a running event loop
This is due to Jupyter already running an event loop, and once Uvicorn calls asyncio.run()
internally, the above error is raised.
As per asyncio.run()
documentation:
This function cannot be called when another asyncio
event loop is
running in the same thread (see relevant asyncio implementation, where the error is raised).
[...]
This function always creates a new event loop and closes it at the
end. It should be used as a main entry point for asyncio
programs, and
should ideally only be called once.
Solution 1
If you wouldd like to run uvicorn
from an already running async
environment, use uvicorn.Server.serve()
instead (you could add the below to a new code cell in your Jupyter notebook, and then run it):
import asyncio
import uvicorn
if __name__ == "__main__":
config = uvicorn.Config(app)
server = uvicorn.Server(config)
await server.serve()
or, get the current (running) event loop, using asyncio.get_running_loop()
, and then call loop.create_task()
for creating a task to run inside the event loop for the current thread:
import asyncio
import uvicorn
if __name__ == "__main__":
config = uvicorn.Config(app)
server = uvicorn.Server(config)
loop = asyncio.get_running_loop()
loop.create_task(server.serve())
Solution 2
Alternatively, you can use nest_asyncio
, which allows nested use of asyncio.run()
and loop.run_until_complete()
:
import nest_asyncio
import uvicorn
if __name__ == "__main__":
nest_asyncio.apply()
uvicorn.run(app)