为什么Popen在Django视图中使用时会挂起?

时间:2014-07-27 08:42:18

标签: python django asynchronous web

在我的一个Django视图中,我需要启动一个可能需要几分钟才能完成的异步作业。由于Celery +消息队列对于此任务来说太过分了,我使用subprocess.Popen创建了一个子进程,如下所示:

args = ['python', SCRIPT_PATH, "&"];
try:
    subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Async call
except:
    pass
return HttpResponse("Job submitted")

我使用nginx + gunicorn来运行我的django应用程序。当我启动服务器并打开shell会话时,上面的代码工作正常。 但是当我关闭shell会话时,代码停止工作并挂起在Popen行中。

我想这是关于stdout / stderr参数,但我不知道如何更改它以使其工作。

====== EDIT ===========

这就是我在脚本中所做的:我使用selenium webdriver + phantomjs加载网页并提交表单,在此过程中,selenium或phantomjs写入标准输出或标准错误。当我在一个shell中启动gunicorn,然后关闭shell会话时,selenium或phantom的写入失败。 当我启动gunicorn时,其输出重定向到这样的文件:

gunicorn app.wsgi > /tmp/gunicorn.log &
问题消失了。

1 个答案:

答案 0 :(得分:3)

虽然我无法确定Popen线路阻塞的原因,但我可以提出一个替代方案。另外,我不确定你需要“&”选项也是。

您可以将NamedTemporaryFiles用于stdout和stderr错误流,例如

from tempfile import NamedTemporaryFile
output = NamedTemporaryFile(delete=False)
error = NamedTemporaryFile(delete=False)
Popen(args, stdout=output, stderr=error) 

这不会阻止。我认为你已经完成了Popen完成后要做的事情。

Popen文档有关于PIPE对象的警告。我在这里粘贴它是为了完整

The data read is buffered in memory, so do not use this method if the data size is large or unlimited.