I am learning FastAPI and I have this example.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
I saved the script as main.ipynb
The tutorial says to run this line of code in the command line: uvicorn main:app --reload
I am getting this error:
(venv) PS C:\Users\xxx\xxxx> uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [21304] using WatchFiles
ERROR: Error loadinimport module "main".INFO: Stopping reloader process [21304]
The reason is because I am using .ipynb
as opposed to .py
.
How can i fix this error while using .ipynb.
Thanks so much
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.
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())
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)