Windows下Uvicorn启动FastAPI时Psycopg事件循环配置无效问题
问题根因
配置不生效、加--reload就正常的核心原因是事件循环策略的设置时机不对:
- Windows环境下Python 3.8及以上版本,asyncio默认使用
ProactorEventLoop,而Psycopg的异步模式不兼容该事件循环,必须切换为WindowsSelectorEventLoopPolicy对应的Selector事件循环。 - 你直接用
uvicorn src.main:app常规模式启动时,Uvicorn会在加载你的src.main模块之前,就提前完成事件循环初始化、数据库连接池的前置准备工作。你写在main文件里的策略配置代码执行时,不兼容的ProactorEventLoop已经创建完成,后续Psycopg检测到的还是非法的事件循环,自然重复抛出相同错误。 - 带
--reload参数启动时,Uvicorn会先启动一个仅负责文件监控的父进程,实际运行业务逻辑的是后续拉起的独立子进程。子进程加载你的业务代码、执行你写的策略设置的时机,刚好在子进程自身的事件循环创建之前,因此配置可以正常生效,不会触发兼容报错。但reload模式本身是为开发环境设计的,重载逻辑会带来额外性能损耗、稳定性差,不能用于生产部署。
可行解决方案
按推荐优先级排序:
- 方案1(Python 3.10及以上版本适用):通过环境变量+Uvicorn启动参数强制指定事件循环实现,无需修改业务代码,稳定性最高。
先在当前PowerShell会话中设置事件循环策略环境变量:
再调整启动命令,强制指定asyncio作为事件循环实现:$env:PYTHONASYNCIO_EVENTLOOP_POLICY="asyncio.WindowsSelectorEventLoopPolicy"uvicorn src.main:app --port 2314 --loop asyncio - 方案2(全Python版本通用):自定义启动入口文件,把事件循环策略设置放在所有业务逻辑、框架导入逻辑的最顶部,从根源上避免Uvicorn提前初始化事件循环。
在项目根目录新建run.py,注意事件循环配置必须放在所有导入语句最前面,不能调整顺序:
后续启动服务直接执行import asyncio asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) import uvicorn from src.main import app if __name__ == "__main__": uvicorn.run(app, port=2314)python run.py即可,无需再使用原来的命令行直接指定app模块的启动方式。
注意不要在业务代码的顶层作用域(即协程/异步函数外部)调用asyncio.get_event_loop(),该调用会触发事件循环提前实例化,导致后续的策略设置完全失效。
内容的提问来源于stack exchange,提问作者Steeven Delucis
相关产品推荐
相关产品推荐

