2009-08-31 55 views

回答

20

subprocess模塊將成爲您的朋友。開始這個過程得到一個Popen對象,然後將它傳遞給像這樣的函數。請注意,這僅在超時時引發異常。如果需要,您可以捕獲異常並在Popen流程中調用kill()方法。 (殺死在Python 2.6是新的,順便說一句)

import time 

def wait_timeout(proc, seconds): 
    """Wait for a process to finish, or raise exception after timeout""" 
    start = time.time() 
    end = start + seconds 
    interval = min(seconds/1000.0, .25) 

    while True: 
     result = proc.poll() 
     if result is not None: 
      return result 
     if time.time() >= end: 
      raise RuntimeError("Process timed out") 
     time.sleep(interval) 
8

至少有2種方式,通過使用psutil只要你知道進程的PID做到這一點。 假設過程中創建這樣:

import subprocess 
subp = subprocess.Popen(['progname']) 

...你能得到它的創建時間在一個繁忙的循環是這樣的:

import psutil, time 

TIMEOUT = 60 * 60 # 1 hour 

p = psutil.Process(subp.pid) 
while 1: 
    if (time.time() - p.create_time) > TIMEOUT: 
     p.kill() 
     raise RuntimeError('timeout') 
    time.sleep(5) 

...或者乾脆,你可以這樣做:

import psutil 

p = psutil.Process(subp.pid) 
try 
    p.wait(timeout=60*60) 
except psutil.TimeoutExpired: 
    p.kill() 
    raise 

此外,當你在它,你可能有興趣在以下額外的API:

>>> p.status() 
'running' 
>>> p.is_running() 
True 
>>> 
2

我有一個類似的問題,並找到了答案。只是爲了完整性,我想添加另一種方式是如何的給定時間後終止掛起的進程:蟒蛇信號庫 https://docs.python.org/2/library/signal.html

從文檔:

import signal, os 

def handler(signum, frame): 
    print 'Signal handler called with signal', signum 
    raise IOError("Couldn't open device!") 

# Set the signal handler and a 5-second alarm 
signal.signal(signal.SIGALRM, handler) 
signal.alarm(5) 

# This open() may hang indefinitely 
fd = os.open('/dev/ttyS0', os.O_RDWR) 

signal.alarm(0)   # Disable the alarm 

既然你想產卵一個新的過程無論如何,這可能不是你的問題最好的解決方案,但。

1

一個很好的被動的方式也是通過使用threading.Timer並設置回調函數。

from threading import Timer 

# execute the command 
p = subprocess.Popen(command) 

# save the proc object - either if you make this onto class (like the example), or 'p' can be global 
self.p == p 

# config and init timer 
# kill_proc is a callback function which can also be added onto class or simply a global 
t = Timer(seconds, self.kill_proc) 

# start timer 
t.start() 

# wait for the test process to return 
rcode = p.wait() 

t.cancel() 

如果進程及時完成,wait()結束並且代碼在此繼續,cancel()將停止計時器。如果同時計時器耗盡並在單獨的線程中執行kill_proc,則wait()也將在此處繼續,而cancel()將不執行任何操作。通過rcode的價值,你會知道我們是否已經超時。最簡單的kill_proc :(你當然可以做任何額外的事情)

def kill_proc(self): 
    os.kill(self.p, signal.SIGTERM) 
相關問題