2010-06-06 57 views
4

我想在多線程python程序的每個線程中執行一個外部程序。以指定的最大運行時間運行外部程序

假設最大運行時間設置爲1秒。如果啓動的過程在1秒內完成,主程序將捕獲其輸出以供進一步處理。如果它在1秒內沒有完成,主程序只是終止它並開始另一個新進程。

如何實現這個?

+0

相關:[子帶超時](http://stackoverflow.com/q/1191374/4279) – jfs 2015-01-06 06:59:03

+0

相關:[停止讀在Python過程輸出,而不掛?](HTTP: //stackoverflow.com/a/4418891/4279) – jfs 2015-01-06 06:59:48

回答

6

你可以定期輪詢:

import subprocess, time 

s = subprocess.Popen(['foo', 'args']) 
timeout = 1 
poll_period = 0.1 
s.poll() 
while s.returncode is None and timeout > 0: 
    time.sleep(poll_period) 
    timeout -= poll_period 
    s.poll() 
if timeout <= 0: 
    s.kill() # timed out 
else: 
    pass # completed 

然後,您可以只把上面的功能,並啓動它作爲一個線程。

+0

它不會捕獲孩子的輸出。 – jfs 2015-01-06 07:06:04

1

linux上令人討厭的黑客攻擊是使用timeout程序來運行該命令。但是,您可以選擇更好的所有Python解決方案。

2

這是輔助函數使用:

def run_with_timeout(command, timeout): 
    import time 
    import subprocess 

    p = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

    while timeout > 0: 
     if p.poll() is not None: 
      return p.communicate() 
     time.sleep(0.1) 
     timeout -= 0.1 
    else: 
     try: 
      p.kill() 
     except OSError as e: 
      if e.errno != 3: 
       raise 
    return (None, None) 
+0

喜歡它:-)適合我們 - 非常感謝你! – 2013-04-15 21:05:25

+0

1.如果'command'生成大輸出(足以填充其OS stdout/stderr管道緩衝區),則不會返回任何輸出。您應該在等待超時時讀取輸出。 2.(小細節)如果'timeout'很大,那麼循環會漂移,因爲'time.sleep(0.1)'可以少睡/超過'0.1'秒。你可以使用'while endtime> timer():'來代替。 – jfs 2015-01-06 07:05:25

1

這裏是使用pexpect模塊(我需要捕捉程序的輸出才跑進超時,我沒能做到的解決方案這與subprocess.Popen):

import pexpect 

timeout = ... # timeout in seconds 

proc = pexpect.spawn('foo', ['args'], timeout = timeout) 

result = proc.expect([ pexpect.EOF, pexpect.TIMEOUT]) 

if result == 0: 
    # program terminated by itself 
    ... 
else: 
    # result is 1 here, we ran into the timeout 
    ... 

print "program's output:", print proc.before