我必须在Flask应用程序中做一些长时间的工作。我想异步完成。只需开始工作,然后从javascript检查状态。
我正在尝试做一些类似的事情:
@app.route('/sync')
def sync():
p = Process(target=routine, args=('abc',))
p.start()
return "Working..."
但这就造就了不复存在的持枪工人。
如何解决?我应该用芹菜之类的东西吗?
有很多选项。你可以开发自己的解决方案,使用Celery或Twisted(我相信还有更多的选择,但这些是最常见的)。
开发您的内部解决方案并不困难。您可以使用Python标准库的multiprocessing
模块:
- 当任务到达时,您将在数据库中插入一行,其中包含任务id和状态
- 然后启动一个流程来执行工作,该工作将在完成时更新行状态
- 您可以有一个视图来检查任务是否完成,这实际上只是检查相应的中的状态
当然,你必须考虑你想把计算结果存储在哪里,以及错误会发生什么。
与芹菜搭配也很容易。它看起来如下。定义异步执行的函数:
@celery.task
def mytask(data):
... do a lot of work ...
然后,不要像mytask(data)
那样直接调用任务,而是使用delay
方法:
result = mytask.delay(mydata)
最后,您可以使用ready
:检查结果是否可用
result.ready()
但是,请记住,要使用Celery,您必须运行一个外部工作进程。
我从来没有看过Twisted,所以我不能告诉你它是否比这个复杂(但做你想做的事情也应该没问题)。
无论如何,这些解决方案中的任何一个都应该适用于Flask。要检查结果,根本不重要如果您使用Javascript。只需使检查状态的视图返回JSON(您可以使用Flask的jsonify
)。
我会使用诸如rabbitmq或activemq之类的消息代理。flask进程将向消息队列中添加作业,而长时间运行的工作进程(或池或工作进程)将从队列中删除作业以完成这些作业。工作进程可以更新数据库,以允许烧瓶服务器了解作业的当前状态,并将此信息传递给客户端。
用芹菜似乎是一种很好的方法。