Flask 2.0 的 async 路由需全程异步,同步调用(如 requests.get、time.sleep)会阻塞事件循环;必须使用 ASGI 服务器(如 uvicorn)并配置异步数据库驱动,钩子函数不支持 async,CPU 密集型任务应交由 ProcessPoolExecutor 处理。

Flask 2.0 的 async 路由本身不会阻塞,但只要里面混入一个同步调用,整个协程就卡死——这不是 Flask 的 bug,而是 asyncio 事件循环的硬性规则。
async 视图必须全程异步,否则退化为“伪异步”
写了 async def 只是告诉 Flask:“这个函数我打算用 await”,但真正决定是否阻塞的,是函数体内每一行代码的 IO 类型。
- 只要出现
requests.get()、smtplib.SMTP().sendmail()、open().read()、time.sleep()这类同步调用,事件循环立刻被锁住,所有并发请求排队等待 -
aiohttp、httpx.AsyncClient、asyncpg才是真正的异步替代品;它们不抢主线程,而是注册回调等系统通知 - 哪怕只有一处
os.listdir(),也得用await asyncio.to_thread(os.listdir, path)包一层,否则照样阻塞
WSGI 服务器下 async 视图根本跑不起来
用 flask run 启动时,底层仍是 Werkzeug 的 WSGI 服务器,它压根不支持 asyncio。这时候 async 视图要么报 RuntimeError: There is no current event loop,要么静默退化成同步执行——你以为在并发,其实还是串行。
- 必须换 ASGI 服务器:
uvicorn main:app或hypercorn main:app -
gunicorn需搭配--worker-class=uvicorn.workers.UvicornWorker,不能用默认的 sync worker - 别信
flask[async]这个包名——它只是装了asgiref和wrapt,不等于自动异步
数据库和上下文容易被忽略的陷阱
很多人以为 ORM 换成 SQLAlchemy 2.0+ 就万事大吉,结果发现 session.execute() 还是慢。问题出在配置和用法上。
立即学习“Python免费学习笔记(深入)”;
- 必须显式创建
create_async_engine(..., future=True),且 URL 前缀要是postgresql+asyncpg://或mysql+aiomysql:// -
session.query().all()是同步写法,得换成await session.scalars(select(...)).all() -
before_request钩子不支持 async——你定义成async def before_request(),Flask 也不会await它,只会当成普通函数调用,协程对象泄漏,内存缓慢上涨
最常被低估的一点:async 视图里没有魔法,它只是把“等网络响应”这件事从线程阻塞换成了事件循环挂起。一旦你把 CPU 密集型操作(比如解析大 JSON、压缩文件)直接塞进去,照样拖垮吞吐量——这种时候该上 ProcessPoolExecutor,而不是硬撑着用 await。



















