能否在setup.py中通过入口点以编程方式运行uvicorn?
解决方案
要同时满足setup.py入口点启动和Uvicorn官方建议,核心是避免在模块顶层直接调用uvicorn.run,而是将启动逻辑封装到函数中,同时保留if __name__ == '__main__'代码块支持直接运行脚本。
实现步骤:
组织代码结构
在你的服务模块(比如my_service/service.py)中,将FastAPI应用定义和启动逻辑分离:import uvicorn from fastapi import FastAPI # 定义你的FastAPI应用 app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"} # 封装启动逻辑到main函数 def main(): uvicorn.run( "my_service.service:app", host="0.0.0.0", port=8000, reload=True ) # 支持直接运行脚本启动(符合官方建议) if __name__ == "__main__": main()配置setup.py入口点
保持你原来的入口点配置,指向上述的main函数:'entry_points': { 'console_scripts': [ 'my_service=my_service.service:main', ], },
为什么这样可行?
- 符合Uvicorn官方建议:启动逻辑不在模块顶层,
uvicorn.run仅在函数被调用时执行。当开启reload=True时,Uvicorn重新加载模块不会重复触发启动逻辑,因为模块顶层没有直接调用uvicorn.run。 - 同时支持两种启动方式:
- 直接运行脚本:
python my_service/service.py,此时__name__ == '__main__'触发main()调用。 - 通过入口点启动:安装包后直接执行
my_service命令,调用main()函数启动服务。
- 直接运行脚本:
额外注意事项
如果使用reload=True,确保Uvicorn能正确找到你的应用模块。路径"my_service.service:app"是相对于Python环境的模块路径,只要你的包结构正确(my_service是可导入的包),这个路径就能正常工作。
内容的提问来源于stack exchange,提问作者tread
相关产品推荐
相关产品推荐

