2014-04-14 88 views
1

運行以下命令:yes | head -1,從外殼,輸出y。使用Python的子模塊與外殼無限期掛起稱之爲:Python子進程.Popen塊與外殼和管道

import subprocess 

arg = "yes | head -1" 
process = subprocess.Popen(arg, 
    shell=True, 
    stdout=subprocess.PIPE, 
    stderr=subprocess.PIPE, 
) 

print "Command started: %d" % process.pid 
r = process.communicate() 
print "Command ended: %s %s" % r 

殺外生使用kill沒有幫助的過程中,也沒有使子進程它的使用preexec_fn=os.setsid會議領導。

什麼可能導致這種行爲,並有反正我可以阻止它?

我運行蟒蛇2.7.3和我/bin/shGNU bash, version 3.2.48(1)-release (x86_64-apple-darwin12)

+0

use'「命令結束:%r」%(r,)'因爲'r'是一個元組。 – jfs

+0

我無法在Ubuntu上重現Python 2.7。它工作正常+/- [預期的「寫」錯誤](http://stackoverflow.com/q/22077881/4279)。 – jfs

+0

謝謝,那個鏈接足以解決它! – sobel

回答

0

因此,原來,這是由於與subprocess模塊Exec之前蟒蛇不復位信號處理的一個已知問題引起的。

這是導致'yes' reporting error with subprocess communicate(),除了與GNU yes同樣的問題,由寫入返回的EPIPE導致程序中止,而用BSD yes(其在OS X據我可以告訴使用),則寫入的返回代碼沒有被檢查,所以沒有SIGPIPEyes將不會終止。

它可以通過固定的向後移植代碼reset_signals,如在上述鏈接的問題:

def restore_signals(): 
    signals = ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ') 
    for sig in signals: 
     if hasattr(signal, sig): 
      signal.signal(getattr(signal, sig), signal.SIG_DFL) 

然後在Popen呼叫設定preexec_fn=restore_signals