2017-09-09 58 views
0

這裏是我的代碼:使用wget包裹在python2.7子運行永遠

import subprocess 
from subprocess import Popen, PIPE 

cmdlist = ['wget', '--no-host-directories', '--mirror', '--no-parent', '--reject', '\'index.html*\'', 'http://abc.blah.com/dir/'] 

p = Popen(cmdlist, stdout=PIPE, stderr=PIPE) 
p.name = 'foo' 

while p.poll() is None: 
    print "#", 
    sys.stdout.flush() 
    time.sleep(1) 

(stdout,stderr) = p.communicate() 
returncode = p.returncode 

if returncode == 0: 
    print "Happy" 
else: 
    print "Sad rc = {0}".format(returncode), 
    print "stdout = \"{0}\"".format(stdout.strip()), 
    print "stderr = \"{0}\"".format(stderr.strip()) 

這將運行永遠在一個非常小的目錄。我不明白爲什麼?

回答

1

wget進程最終會被阻塞,因爲如果它寫入的內容足以填充該管道的內核緩衝區,它將等待其stdoutstderr管道變爲可寫。默認情況下,這是管道如何工作的原因:編寫器進程將被放慢速度以適應讀者進程的速度,如果讀者停止閱讀,編寫器將停止編寫(如果讀者退出,編寫器會被終止!)

有幾種不同的方法可以解決這個問題。

  • 爲了防止緩衝器變滿,無論從p.stdoutp.stderr閱讀。小心不要在stdout上阻止,而wgetstderr上被阻止,反之亦然......您必須同時從兩者中讀取。這是p.communicate()如何在內部工作。這是最複雜的解決方案,但是如果您查看Popen._communicate的源代碼subprocess.py,您會看到它應該如何工作。

  • 從您的代碼中刪除while p.poll() is None循環。

  • 請勿將wget重定向到管道,將其重定向到其他東西,如常規文件或/dev/null

+0

我認爲OP的代碼的另一個問題是''--reject','\'index.html * \'''可能實際上不工作。 – Blender

+0

@Blender:這將是一個很好的評論,但如果你在這裏發表評論,OP可能會錯過它:-) –

+0

@Blender你是對的,它沒有工作。你知道爲什麼嗎 ?我怎樣才能使它工作? – abc