子进程阻止Django视图 [英] subprocess blocks Django view
问题描述
从视图调用subprocess.Popen时遇到问题:子过程完成之前,不会显示调用subprocess.Popen的视图.服务器立即发送"200 OK",但不发送页面内容.
我的问题是:这是Django开发服务器的限制还是我做错了?
服务器无法完全挂起,因为可以同时处理其他视图.
已经有有关该主题的一些问题,Google给出了如何繁殖
创建测试项目&应用:
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导入*
urlpatterns =模式('',
(r'^ hello $','subprocess_test.views.hello'),
(r'^ start $','subprocess_test.views.start'),
) -
subprocess_test/views.py
从django.http导入HttpResponse
导入子流程
def hello(request):
返回HttpResponse('Hello world!')def start(请求):
subprocess.Popen(["/bin/sleep","10"])
返回HttpResponse('开始完成')
对其进行测试:
./manage.py运行服务器0.0.0.0:8000
转到 http://127.0.0.1:8000/hello 和 [2011年2月1日07:20:57]"GET/hello HTTP/1.1" 200 12 使用wget: wget http://127.0.0.1:8000/start 2011-02-01 14:31:21(1,05 B/s)-«开始»保存[10] 似乎您并不在乎系统调用的结果,所以我假设您正在尝试进行某种脱机(或后台操作))处理. 我建议采用一种更清洁的方式进行处理,而不是直接执行程序.使用诸如 Gearman 之类的排队系统来排队处理任务,然后让一个单独的工作程序从该队列中消费项目./p> 这样做的好处是可以在出现大流量高峰时保护服务器,因此您不必在每次向该视图发出请求时都派生一个进程.您可以根据自己的决定消费速度快慢,而不受流量的影响. 交通问题可能不是问题,但我个人认为这也是一个更清洁的设计决定. I have a problem calling subprocess.Popen from a view:
The view that calls subprocess.Popen is not displayed until the subprocess finishes.
The server send "200 OK" immediately, but not the content of the page. My question is: Is this a limitation of Django's development server or am I doing it wrong? The server does not completely hangs, as other views can be processed in the meantime. There are already a few questions on that topic and Google gives a few other threads, but I cannot find a clear answer to my question. I believe this is not a python issue as this commands terminate immediately: python -c 'import subprocess; print subprocess.Popen(["/bin/sleep", "10"]).pid'
[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
--2011-02-01 14:31:11-- http://127.0.0.1:8000/start
正在连接至127.0.0.1:8000 ...已连接.
HTTP请求已发送,正在等待响应... 200 OK
长度:未指定[text/html]
保存到:开始"
[< =>]在9,5秒内达到10 --.- K/s
How to reproduce
Create test project & app:
cd /tmp
django-admin.py startproject django_test
cd django_test
./manage.py startapp subprocess_test
Replace urls.py & subprocess_test/views.py with:
urls.py:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^hello$', 'subprocess_test.views.hello'),
(r'^start$', 'subprocess_test.views.start'),
)subprocess_test/views.py
from django.http import HttpResponse
import subprocess
def hello(request):
return HttpResponse('Hello world!')def start(request):
subprocess.Popen(["/bin/sleep", "10"])
return HttpResponse('start done')
Test it:
./manage.py runserver 0.0.0.0:8000
Go to http://127.0.0.1:8000/hello and http://127.0.0.1:8000/start
Test result
"start" takes 10s to load and "hello" can be loaded during that time. For example, I get such a log:
[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
Using 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 [text/html]
Saving to: `start'[ <=> ] 10 --.-K/s in 9,5s
2011-02-01 14:31:21 (1,05 B/s) - « start » saved [10]
It looks like you don't care what the result of the system call is, so I would assume you are trying to do some sort of offline(or background) processing.
I would suggest a cleaner way of going about it rather than directly executing a program. Use a queueing system such as Gearman to queue up processing tasks and then have a separate worker that consumes items from the queue.
This has the advantage of protecting your server when large traffic spikes happen, so you don't fork off a process each time a request to that view is made. You can consume items as slow or as fast as you decide, independent of traffic.
Traffic may not be an issue, but I personally think it is a cleaner design decision as well.
这篇关于子进程阻止Django视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!