subprocess blocks Django view
我从一个视图调用subprocess.Popen时遇到问题:
在子流程完成之前,不会显示调用subprocess.Popen的视图。
服务器立即发送"200 OK",但不发送页面内容。
我的问题是:这是Django开发服务器的限制还是我做错了?
服务器不会完全挂起,因为其他视图可以同时处理。
关于该主题已经有一些问题,谷歌提供了一些其他线索,但我无法找到我的问题的明确答案。
我相信这不是python问题,因为这个命令会立即终止:
python -c 'import subprocess; print subprocess.Popen(["/bin/sleep","10"]).pid'
如何重现
创建测试项目和应用程序:
cd /tmp
django-admin.py startproject django_test
cd django_test
./manage.py startapp subprocess_test
将urls.py和subprocess_test / views.py替换为:
-
urls.py:
来自django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^ hello $','subprocess_test.views.hello'),
(r'^ start $','subprocess_test.views.start'),
) -
subprocess_test / views.py
来自django.http导入HttpResponse
导入子流程
def hello(请求):
返回HttpResponse('Hello world!')def start(请求):
subprocess.Popen(["/ bin / sleep","10"])
返回HttpResponse('开始完成')
测试一下:
./manage.py runserver 0.0.0.0:8000
转到http://127.0.0.1:8000/hello和http://127.0.0.1:8000/start
测试结果
"start"需要10秒才能加载,并且"hello"可以在此期间加载。
例如,我得到这样一个日志:
[01/Feb/2011 07:20:57]"GET /hello HTTP/1.1" 200 12
[01/Feb/2011 07:21:01]"GET /start HTTP/1.1" 200 10
[01/Feb/2011 07:21:01]"GET /hello HTTP/1.1" 200 12
[01/Feb/2011 07:21:02]"GET /hello HTTP/1.1" 200 12
使用wget:
wget http://127.0.0.1:8000/start
--2011-02-01 14:31:11-- http://127.0.0.1:8000/start
Connecting to 127.0.0.1:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified
Saving to: `start'
1 [ <=> ] 10 --.-K/s in 9,5s2011-02-01 14:31:21 (1,05 B/s) - ? start ? saved [10]
看起来你不关心系统调用的结果是什么,所以我假设你正在尝试进行某种离线(或后台)处理。
我会建议一种更简洁的方式,而不是直接执行程序。使用诸如Gearman之类的排队系统来排队处理任务,然后让一个单独的工作人员使用队列中的项目。
这样做的好处是可以在发生大量流量峰值时保护您的服务器,因此每次向该视图发出请求时,您都不会分叉进程。您可以根据您的决定以慢速或快速的方式使用项目,而与流量无关。
交通可能不是问题,但我个人认为这也是一个更清洁的设计决策。
我在使用nginx + uwsgi运行Django时遇到了同样的问题。通常,断点是web服务器的模块,在我的例子中它是uwsgi。添加
我不知道您使用哪个服务器,因此您可以使用各种模块(uwsgi,mod_wsgi,fastcgi)检查此行为,并查看哪种更适合您。
并尝试在后台执行:
1 | subprocess.Popen(["/bin/sleep","10","&"]) |
试试这个
1 2 3 4 | import subprocess x = subprocess.Popen(["/bin/sleep","10"]) x.wait() |