从 Django 内部调用时,Subprocess.Popen 与交互式程序一起挂起

发布于 2024-09-13 07:54:36 字数 1338 浏览 3 评论 0原文

我编写了一个小型 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 方法替换 subprocess 。但即便如此,它也挂在完全相同的地方。同样,如果我从 Django 执行相同的代码,这也会运行。

I have written a small Django App, that executes an interactive program based on user input and returns the output as the result. But for some reason, the subprocess hangs. On verification of the logs I found that a place where a '\n' has to be given as response to a challenge, the response seems to have never been made. Interestingly, if I run the same code from outside of Django, i.e either from a python module or from the interactive shell, subprocess works without a hitch. I am assuming some settings within the environment used by Django are the culprit here. Here are snippets of the code that I've written:

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})

I've tried replacing subprocess with the older os.system method. But even that hangs in the exact same place. Again, this runs too if I were execute same code out of Django.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

忘东忘西忘不掉你 2024-09-20 07:54:36

子流程文档建议您“使用communicate()而不是.stdin.write, .stdout.read 或 .stderr.read 以避免由于任何其他操作系统管道缓冲区填满并阻塞子进程而导致的死锁。”

如果您使用 return p.communicate()[0] 而不是 return p.stdout.read() ,它会起作用吗?

The subprocess documentation suggests that you "use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process."

Does it work if you use return p.communicate()[0] instead of return p.stdout.read()?

老子叫无熙 2024-09-20 07:54:36

我在执行此类操作以获得 Mercurial Tip 版本时遇到了同样的问题:

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) 运行时工作正常,但会导致开发服务器中出现空白页。

我已经在与此相关的错误中徘徊,我能找到的错误似乎已作为重复或已关闭的工作形式关闭。

我关于此问题的原始帖子可在 http://groups.google.com/group/django-users/browse_thread/thread/147ffe75899fd6e?pli=1

I've had the same issue doing this sort of thing to get the mercurial tip version:

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

This works fine when running through apache (mod_wsgi), but causes blank pages in the development server.

I've had a wander around the bugs related to this and the ones I could find seems to be closed as duplicate, or closed worksforme.

My original post about this is available at http://groups.google.com/group/django-users/browse_thread/thread/147ffe75899fd6e?pli=1

瘫痪情歌 2024-09-20 07:54:36

我认为你的问题是“runtest”程序所在的目录。您的视图将在视图所在的同一目录中获取该模块。如果模块位于其他位置,您还可以在 Popen 参数列表中指定“cwd”参数。
我在 Django 开发服务器的视图中使用 Popen 命令,没有任何问题,因此开发服务器不是问题的原因。

I think your problem is the directory where the 'runtest' program is located. You view is going to fetch that module in the same directory where the view is. You can also specify 'cwd' argument in the Popen list of arguments if the module is anywhere else.
I'm using Popen command in a view with Django dev server whithout any problems, so the dev server is not the cause of your problem.

请你别敷衍 2024-09-20 07:54:36

我的问题是我在 Pycharm 中运行 Django。运行 ./manage.py runserver 直接为我解决了这个问题。

My problem was in the fact I was running Django in Pycharm. Running ./manage.py runserver directly fixed it for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文