2010-08-06 80 views
2

我寫了一個小型Django應用程序,它根據用戶輸入執行交互式程序並將結果作爲結果返回。但由於某種原因,子進程掛起。在對日誌進行驗證時,我發現一個'\ n'必須作爲應對挑戰的地方,似乎從未做出迴應。有趣的是,如果我從Django之外運行相同的代碼,即從python模塊或交互式shell運行,子流程可以毫無困難地工作。我假設Django使用的環境中的一些設置是這裏的罪魁禍首。這裏是我寫的代碼片段:Subprocess.Popen在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執行相同的代碼,這也會運行。

+0

你是什麼意思的互動?子處理的runtest程序是否需要輸入它的stdin?我只看到你用一些命令行參數運行它。 – Mark 2010-08-06 13:54:08

+0

你是如何運行django的? 'runserver'? 'modpython'? 'wsgi'? – MattH 2010-08-06 14:45:18

+0

@Mark感謝您的回覆。我想我對互動的使用並不是真的正確。實際上,runtest程序會在網絡中打開一個帶有設備的外殼,並通過響應設備給出的提示進行交互。用戶沒有這樣的交互。 @MattH感謝repsonse。我目前正在使用Django的開發服務器。 – sdzk 2010-08-06 15:07:11

回答

0

subprocess documentation建議您「使用communications()而不是.stdin.write,.stdout.read或.stderr.read以避免由於任何其他OS管道緩衝區填滿和阻止子進程而導致的死鎖。 「

如果您使用return p.communicate()[0]而不是return p.stdout.read(),它會工作嗎?

+0

我已經嘗試了溝通()[0]。但沒有運氣。感謝您的回覆。 – sdzk 2010-08-07 12:21:38

0

我有同樣的問題,做這樣的事情讓善變的提示版本:

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

+0

我應該轉移到Apache並嘗試這一個。看起來像是碰到了與Django開發服務器相關的錯誤。謝謝。 – sdzk 2010-08-09 02:05:13

0

我覺得你的問題出在哪裏了 '的runTest' 程序所在的目錄。您查看的是要在與視圖相同的目錄中獲取該模塊。如果模塊在其他地方,你也可以在Popen參數列表中指定'cwd'參數。 我在Django dev服務器的視圖中使用Popen命令時沒有任何問題,所以開發服務器不是問題的原因。

+0

感謝您的回覆。我試過cwd,但它仍然不能解決我的問題。 – sdzk 2010-08-11 12:18:19