我创建了一个python主应用程序main.py,用uvicorn main.main --reload
调用它。哪个当然运行以下代码。。。
if __name__ == '__main__':
main()
应用程序的这一部分持续运行,读取数据并进行处理,直到手动中止应用程序。我使用asyncio
来运行协同程序。
任务
我想在上面构建一个小的html面板,它可以显示不断计算的数据。
问题
我如何运行main.py的这些后台计算,并仍然使用fastapi和jinja2实现仪表板/网站?
- 构建文件的最佳实践/架构是什么:后台和fastapi应用程序代码?例如,fastapi中是否有一个初始启动函数,我可以在协同程序中调用后台计算,或者反过来调用
- 根据您的建议,您将如何调用应用程序
到目前为止我所取得的成就
我可以在没有任何fastapi代码的情况下运行主应用程序。我可以在没有后台任务的情况下运行仪表板。两人独立工作都很好。但是当我将fastapi的代码添加到具有后台计算的主应用程序中时,它不会运行。(怎么可能?!?我只能调用主应用程序或fastapi应用程序。(
任何建筑概念都值得赞赏。非常感谢。
Fastapi不会运行,因为在它完成计算之前,python解释器无法访问它。您应该独立于主进程启动web应用程序,我强烈建议您使用docker-compose
。正如fastapi建议的那样,您应该使用Dramatiq
或Celery
来执行巨大的后台任务,或者您可以在compose服务中运行单独的服务,例如:
# background.py
if __name__ == '__main__':
main()
# main.py
app = FastAPI()
docker-compose.yml:
services:
web-app-interface:
command: uvicorn main.main ...
my-daemon:
command: python background.py
您可以让它们与消息代理进行通信,例如RabbitMQ等。而且永远不要对uvicorn使用多处理,这可能会导致过程泄漏,因为uvicorn是自己的工人。
一个好的方法是将on_event
装饰器与startup
一起使用。唯一剩下的就是使用asyncio.create_task
来调用后台任务。只要你不等待它,它就不会阻塞,因此fastapi/uvcorn可以继续为任何http请求提供服务。
my_service = MyService()
@app.on_event('startup')
async def service_tasks_startup():
"""Start all the non-blocking service tasks, which run in the background."""
asyncio.create_task(my_service.start_processing_data())
此外,如上所述,任何请求都可以使用该后台服务的数据。
@app.get("/")
def root():
return my_service.value
把MyService
想象成你喜欢的任何一类。Kafka消费、计算等。当然,value
只是ClassMyService的一个示例属性。