为什么在 Jupyter 里跑 uvicorn.run 一定会报错
·
- Jupyter 本身已经启动了 asyncio event loop
uvicorn.run()内部会调用asyncio.run()- 于是:
loop 已存在 → uvicorn 再建 loop → 直接 RuntimeError
👉 这不是你代码的问题,是运行环境冲突
二、正确解决方案(按推荐顺序)
✅ 方案 1(强烈推荐):用 uvicorn.Server(Jupyter 官方解法)
这是唯一干净、可控、不 hack 的方式。
import uvicorn
import asyncio
config = uvicorn.Config(
app,
host="0.0.0.0",
port=port,
log_level="info",
)
server = uvicorn.Server(config)
await server.serve()
📌 关键点:
- 不要用
uvicorn.run() - 直接
await server.serve() - 完全兼容 Jupyter 的 event loop
✅ 方案 2:在后台线程启动 uvicorn(实用但稍脏)
import threading
import uvicorn
def run():
uvicorn.run(app, host="0.0.0.0", port=port)
threading.Thread(target=run, daemon=True).start()
📌 适合:
- 临时调试
- 不想改 FastAPI 结构
⚠ 不适合:
- 长期服务
- 热重载
- 精细生命周期控制
⚠ 方案 3:nest_asyncio(不推荐生产)
import nest_asyncio
nest_asyncio.apply()
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=port)
📌 适合教学 / demo
🚫 不适合真实服务
三、你不该在 Jupyter 里做的事 ❌
uvicorn.run(app, ...)
asyncio.run(uvicorn.run(...))
asyncio.get_event_loop().run_until_complete(...)
👉 都是 反模式
四、最佳实践建议(经验总结)
✅ 开发期
-
Jupyter:只做
- API 逻辑
- 数据验证
- 单元测试
-
终端跑服务:
uvicorn main:app --reload --port 8000
✅ 如果你一定要 Notebook + 服务
👉 只用 Server + await serve()
五、最小可运行示例(FastAPI + Jupyter)
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/")
async def root():
return {"msg": "hello"}
config = uvicorn.Config(app, host="0.0.0.0", port=8000)
server = uvicorn.Server(config)
await server.serve()
更多推荐
所有评论(0)