Flask 3.0 的 flask run 报 RuntimeWarning 是因 WSGI 服务器不支持 ASGI,无法管理 asyncio 事件循环;正确做法是弃用 flask run,改用 uvicorn myapp:app 启动,并确保异步 I/O 使用真正支持 asyncio 的库和 await 调用。

为什么 flask run 会报 RuntimeWarning: Running asyncio.run() in a running event loop
Flask 3.0 虽然支持 async def 视图函数,但自带的 flask run 命令启动的是 WSGI 开发服务器(基于 Werkzeug),它不理解 ASGI 协议,也无法管理 asyncio 事件循环。一旦你定义了异步路由,flask run 就会强行在已运行的事件循环里再调用 asyncio.run(),触发该警告,甚至导致请求卡死或 500 错误。
根本解决办法只有一条:彻底弃用 flask run,改用 ASGI 服务器启动。
- 必须用
uvicorn myapp:app启动(myapp.py中有app实例) - 不能加
--use-reloader或--debug这类 Werkzeug 特有参数 - 确保 Python 环境中安装的是 Flask 3.0+(
pip show flask查版本)
uvicorn 启动时遇到 TypeError: _patch_asyncio.<locals>.run() got an unexpected keyword argument 'loop_factory'</locals>
这是 PyCharm 调试器与新版 uvicorn(0.30+)的典型冲突:PyCharm 的调试补丁重写了 asyncio.run,但没兼容 uvicorn 新增的 loop_factory 参数。
临时绕过方式是禁用 loop_factory,而不是降级 uvicorn:
立即学习“Python免费学习笔记(深入)”;
- 在 PyCharm 的 Run/Debug Configuration 中,把 Command line arguments 改为:
--loop auto --no-access-log(显式指定 loop 类型,避免自动注入loop_factory) - 或者直接在代码里启动(开发阶段可接受):
if __name__ == "__main__":<br> import uvicorn<br> uvicorn.run("myapp:app", loop="auto") - 生产环境不用 PyCharm 调试,此问题天然不存在
异步路由里用了 time.sleep() 或同步数据库驱动,为什么还是阻塞?
Flask 3.0 的 async 支持只负责调度,不负责 I/O 非阻塞。如果你在 async 视图里调用 time.sleep(2)、requests.get() 或原生 sqlite3.connect(),整个事件循环会被挂起,所有并发请求都卡住。
真正有效的异步 I/O 必须满足两个条件:
- 底层库本身支持 asyncio(如
aiohttp、aiomysql、asyncpg、httpx) - 调用时用了
await(例如await httpx.get(...),不是httpx.get(...)) - 同步操作必须包进
asyncio.to_thread()(Python 3.9+)或loop.run_in_executor(),否则无意义
Flask + Uvicorn 部署时,如何避免和 Flask-SocketIO 冲突?
Flask-SocketIO 和原生 uvicorn 不兼容——前者依赖 eventlet 或 gevent,后者基于 asyncio。两者事件循环模型不同,硬凑会导致连接失败或 400 错误。
二选一才是务实做法:
- 要 WebSocket:放弃
uvicorn,改用eventlet或gevent启动(eventlet.monkey_patch()+socketio.run(app, ...)) - 要原生 async 路由:去掉
Flask-SocketIO,换用FastAPI+WebSocket或纯前端fetch/SSE - 混合需求极少见,强行共存需自研适配层,维护成本远高于重构
最容易被忽略的是:async 路由的性能收益,完全取决于你是否真的替换了 I/O 操作。写个 async def 但里面全是 time.sleep 或 sqlite3,只是给解释器多加了一层协程调度开销而已。


















