我需要在我的Flask应用程序中完成一些耗时的工作,并且我希望能够异步进行。只需开始工作,然后从Javascript检查状态。
我正在尝试实现以下功能:
@app.route('/sync')
def sync():
p = Process(target=routine, args=('abc',))
p.start()
return "Working..."
但是这会导致gunicorn工作进程变成僵尸进程。
如何解决?我应该使用类似Celery的东西吗?
我需要在我的Flask应用程序中完成一些耗时的工作,并且我希望能够异步进行。只需开始工作,然后从Javascript检查状态。
我正在尝试实现以下功能:
@app.route('/sync')
def sync():
p = Process(target=routine, args=('abc',))
p.start()
return "Working..."
有许多选项。您可以开发自己的解决方案,使用Celery或Twisted(我确信还有更多现成的选项,但这些是最常见的)。
开发自己的内部解决方案并不难。您可以使用Python标准库中的模块:
当然,您必须考虑要将计算结果存储在何处以及出现错误时会发生什么。
选择Celery也很容易。看起来像下面这样。 定义要异步执行的函数:
@celery.task
def mytask(data):
... do a lot of work ...
那么,不要直接调用任务,比如 mytask(data)
,这会立即执行它,而是使用 delay
方法:
result = mytask.delay(mydata)
最后,你可以使用ready
来检查结果是否可用:
result.ready()
请记住,要使用Celery,您必须运行一个外部的worker进程。
我从未了解过Twisted,所以我无法告诉您它是否比这个更加复杂(但也应该能够满足您想做的事情)。
无论如何,任何这些解决方案都应该与Flask配合得很好。要检查结果,完全不需要使用Javascript。只需创建检查状态并返回JSON的视图(您可以使用Flask的jsonify
)。
使用Celery似乎是一个不错的选择。
multiprocessing
时,它会导致gunicorn工作进程失效。 - sashabValueError: I/O operation on closed file
的错误。看起来我需要使用Popen。设置Process().daemon = True
也没有帮助。 - sashabp.daemon = True
是不够的。如果你在nix平台上,我建议使用python-daemon或者使用这个代码片段,它直接调用操作系统的fork
而不是multiprocessing
或Popen
。如果你在Windows上,你必须创建一个服务*而不是守护进程。无论如何,最可移植的解决方案可能是使用Celery或Twisted。 - pacha