如何在 Jupyter 中运行 FastAPI 应用程序

797 阅读2分钟

如何在 Jupyter 中运行 FastAPI 应用程序

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

例子.

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

我将脚本另存为main.ipynb

在命令行中运行下面这行代码:uvicorn main:app --reload

我收到以下错误:

(venv) PS C:\Users\xxx\Desktop\Python Yamed\SaadAPI> 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]

原因是我用的是.ipynb,而不是.py.

如何在使用.ipynb时修复此错误.

非常感谢

推荐答案

如果您try 像往常一样在Jupyter中启动服务器,例如:

import uvicorn

if name == "main": uvicorn.run(app)

您将收到以下错误:

RuntimeError: asyncio.run() cannot be called from a running event loop

这是因为Jupyter已经运行了一个事件循环,一旦Uvicorn在内部调用asyncio.run(),就会引发上述错误.

根据asyncio.run()个文档:

当另一个asyncio事件循环 在同一线程中运行(请参见引发错误的relevant asyncio implementation).

此函数始终创建一个新的事件循环,并在 结束.它应该被用作asyncio个程序的主要入口点,以及 理想情况下应该只被称为once.

解决方案1

如果您希望从已经运行的async环境中运行uvicorn,请改用uvicorn.Server.serve()(将以下代码添加到您的Jupyter笔记本中的新代码单元格中并执行它):

import asyncio
import uvicorn

if __name__ == "__main__":
    config = uvicorn.Config(app)
    server = uvicorn.Server(config)
    await server.serve()
INFO:     Started server process [16632]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [16632]

或者,获取当前事件循环(使用asyncio.get_event_loop()),并调用loop.create_task()在事件循环内为当前线程创建一个任务:

import asyncio
import uvicorn

if __name__ == "__main__":
    config = uvicorn.Config(app)
    server = uvicorn.Server(config)
    loop = asyncio.get_event_loop()
    loop.create_task(server.serve())
<Task pending name='Task-8' coro=<Server.serve() running at D:\EMC2\python311\Lib\site-packages\uvicorn\server.py:63>>



INFO:     Started server process [16632]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

解决方案2

或者,也可以使用nest_asyncio,这允许嵌套使用asyncio.run()loop.run_until_complete():

import nest_asyncio
import uvicorn

if __name__ == "__main__":
    nest_asyncio.apply()
    uvicorn.run(app,
        host="127.0.0.1",
        port=8001)
INFO:     Started server process [16632]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit)
Exception in callback Task.task_wakeup(<Future finished result=None>)
handle: <Handle Task.task_wakeup(<Future finished result=None>)>
Traceback (most recent call last):
  File "D:\EMC2\python311\Lib\asyncio\events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
RuntimeError: Cannot enter into task <Task pending name='Task-8' coro=<Server.serve() running at D:\EMC2\python311\Lib\site-packages\uvicorn\server.py:81> wait_for=<Future finished result=None>> while another task <Task pending name='Task-3' coro=<Kernel.dispatch_queue() running at D:\EMC2\python311\Lib\site-packages\ipykernel\kernelbase.py:524> cb=[_wrap_awaitable.<locals>.<lambda>() at D:\EMC2\python311\Lib\site-packages\tornado\gen.py:852, IOLoop.add_future.<locals>.<lambda>() at D:\EMC2\python311\Lib\site-packages\tornado\ioloop.py:699]> is being executed.


INFO:     127.0.0.1:55636 - "GET / HTTP/1.1" 200 OK


INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [16632]


INFO:     127.0.0.1:55652 - "GET / HTTP/1.1" 200 OK

jupyter nbconvert --to markdown "Python 如何在 Jupyter 中运行 FastAPI 应用程序.IPYNB"

UPDATE 2024-01-22 BY YULIKE