我正在从python脚本运行程序(目前使用os.system
)。但是,有时程序会挂起,如果在一定时间间隔后没有写入stdout或stderr,我想杀死它。程序上的简单超时将无法工作,因为此代码通常会运行很长时间(数小时到数天),有时它会在它还有很长的路要走之前挂起。
似乎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 :(得分:1)
尝试使用signal.alarm
在收到每一行后设置一个计时器,然后通过检查自上一行以来是否经过了太多时间来处理SIGALRM
。
答案 1 :(得分: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