运行一个进程,如果一个小时内不结束就杀死它
我需要在Python中做以下事情。我想要启动一个进程(可以用subprocess模块),并且:
- 如果这个进程正常结束,就从它结束的那一刻继续执行;
- 如果这个进程“卡住”了,超过(比如说)一个小时还没有结束,就把它杀掉,然后继续执行(可能还会再尝试一次,循环进行)。
有什么优雅的方法可以做到这一点吗?
5 个回答
6
我之前也有类似的问题,找到了这个答案。为了完整起见,我想再补充一种方法,教你如何在一定时间后结束一个卡住的进程:可以使用Python的信号库。你可以在这里查看详细信息: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
不过,由于你本来就想要启动一个新进程,这个方法可能不是解决你问题的最佳选择。
11
只要你知道进程的PID(进程标识符),使用psutil有至少两种方法可以做到这一点。
假设这个进程是这样创建的:
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
>>>
33
subprocess
模块会是你的好帮手。你可以启动一个进程来获取一个Popen
对象,然后把这个对象传给一个函数。需要注意的是,这个方法只会在超时时抛出异常。如果你想的话,可以捕捉这个异常,并对Popen
进程调用kill()
方法。(顺便说一下,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)