我需要在Python中執行以下操作。我想生成一個進程(子進程模塊?),並且:Python:運行一個進程並殺死它,如果它不在一小時內結束
- 如果進程正常結束,要從其終止的那一刻開始繼續;
- 如果否則進程「卡住」並且不在一小時內終止(例如),以殺死它並繼續(可能在循環中再次嘗試)。
什麼是最優雅的方式來實現這一目標?
我需要在Python中執行以下操作。我想生成一個進程(子進程模塊?),並且:Python:運行一個進程並殺死它,如果它不在一小時內結束
什麼是最優雅的方式來實現這一目標?
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)
至少有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
>>>
我有一個類似的問題,並找到了答案。只是爲了完整性,我想添加另一種方式是如何的給定時間後終止掛起的進程:蟒蛇信號庫 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
既然你想產卵一個新的過程無論如何,這可能不是你的問題最好的解決方案,但。
一個很好的被動的方式也是通過使用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)