我已经编写了一个小型Django应用程序,该应用程序根据用户输入执行一个交互式程序,并将输出作为结果返回。但是由于某种原因,子进程挂起。在对日志进行验证时,我发现必须对响应发出“ \ n”的地方,但似乎从未做出过回应。有趣的是,如果我从Django外部运行相同的代码,即从python模块或从交互式shell运行,则子过程可以顺利进行。我假设Django使用的环境中的某些设置是这里的罪魁祸首。以下是我编写的代码片段:
def runtests(test_name, selective=False, tests_file=''):
if selective:
run_cmd = ['runtest', '--runfromfile', tests_file, test_name]
else:
run_cmd = 'runtest %s' % (test_name)
print 'Executing command .. '
print run_cmd
p = subprocess.Popen(run_cmd, shell=False, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
return p.stdout.read()
def result(request):
test_name = request.GET['test_name']
if not test_name:
return render_to_response('webrun/execute.html', {'error_flag':True})
in_file = os.path.abspath('webrun/log/%s_in.xml' % test_name)
suites = dict([(field[len('suite_'):],value)
for field,value in request.GET.items()
if field.startswith('suite_')])
if suites:
_from_dict_to_xml(suites, in_file, test_name)
output = runtests(test_name, bool(suites), in_file)
return render_to_response('webrun/result.html', {'output':output})
我已经尝试用较旧的os.system方法替换子流程。但是,即使挂在完全相同的地方。同样,如果我从Django中执行相同的代码,也可以运行。
subprocess documentation建议您“使用communication()而不是.stdin.write,.stdout.read或.stderr.read,以避免由于任何其他OS管道缓冲区填满并阻塞子进程而导致死锁。 “
如果使用return p.communicate()[0]
而不是return p.stdout.read()
可以使用吗?
我在进行此类操作以获取水银笔尖版本时遇到了相同的问题:
import subprocess
lProcess = subprocess.Popen(["hg","tip"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
lOutput = lProcess.stdout.readline()
lTipRevision = lOutput[10:].strip()
lTipRevision = lTipRevision[:lTipRevision.find(":")].strip()
print "Repository tip version is %s" % lTipRevision
这在通过apache(mod_wsgi)运行时效果很好,但是在开发服务器中导致空白页。
我已经绕过与此相关的错误,我发现这些错误似乎已被关闭,因为它们是重复的,或者是封闭的workforme。
我对此的原始帖子可在http://groups.google.com/group/django-users/browse_thread/thread/147ffe75899fd6e?pli=1中找到>>
我认为您的问题是“运行测试”程序所在的目录。您的视图将在该视图所在的目录中获取该模块。如果模块在其他任何位置,也可以在Popen参数列表中指定'cwd'参数。我在没有任何问题的Django开发服务器视图中使用Popen命令,因此开发服务器不是导致问题的原因。
我的问题是我在Pycharm中运行Django。运行./manage.py runserver
直接为我修复了它。