2013-03-17 138 views
0

我從一個Python腳本運行的程序(目前os.system)殺子。但是,有時程序掛起,在一個點,我想殺死它,如果沒有在一定的時間間隔後寫入到標準輸出或標準錯誤。對程序的簡單超時將無法正常工作,因爲這些代碼通常運行了很長一段時間(數小時至數天),有時它掛起它仍然有很長的路要走。如何如果標準輸出沒有活動/標準錯誤

看來subprocess.Popen是要走的路,但我還沒有找到如何做到這一點的好例子。我也想把stdout/stderr寫入一個文件。

基於一些例子,我想是這樣的:

p = Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None) 

while True: 
    line = p.stdout.readline() 
    outfile.write(line) 
    # save current time or something, compare to time of 
    # previous loop, if larger than timeout, kill process 

但我不知道如何實現時間循環,以及如何確保while不會永遠運行時該過程最終會自行終止(並且不會掛起)。任何指針將不勝感激。

+0

爲什麼不修復了子進程因此它不掛? – 2013-03-17 13:45:52

+0

@JohnZwinck,當然是最好的解決方案。但是,在這種情況下,這種情況很少發生,很難複製。在某些情況下,由於進程外的原因(例如文件系統等),它也會掛起。 – tiago 2013-03-17 14:02:20

回答

1

嘗試使用signal.alarm在接收到每一行後設置一個計時器,然後通過檢查從最後一行開始是否已經過了太多時間來處理SIGALRM

+0

謝謝。 'signal.alarm'真的很酷。我設法使用它來實現我想要的。 – tiago 2013-03-19 07:40:32

1

爲了完整起見,這裏是我結束了使用,利用的建議signal.alarm的代碼:

import time 
import shlex 
import subprocess 

logfile = open(log, 'w', 1) 
# cmd is command to run 
args = shlex.split(cmd) # tokenise args list 
p = subprocess.Popen(args, shell=False, bufsize=0, stdin=None, 
        stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 

def _handler(signum, frame): 
    print('Timeout of %s min reached, stopping execution' % timeout) 
    p.kill() 
    time.sleep(30) # to ensure no ghost process is left running 
    raise RuntimeError('Timeout') 

signal.signal(signal.SIGALRM, _handler) 
try: 
    while True: 
     signal.alarm(int(timeout)) 
     inline = p.stdout.readline() 
     if not inline: 
      break 
     logfile.write(inline) 
     signal.alarm(0) 
except RuntimeError: 
    logfile.close() 
    return 0 

p.communicate() # wait for process to finish, get return code 
logfile.close() 
return p.returncode 
+0

你確定你的代碼正在工作嗎?我試過了,但子進程立即死亡。 – 2016-10-15 15:53:47

+0

@PedroLobito是的,我經常運行多年。也許它不是很便攜,不適用於所有系統?我已經在Linux和Python 2.7上運行它。 – tiago 2016-10-18 18:01:13

+0

謝謝@tiago,我會再試一次。 – 2016-10-18 21:30:52

相關問題