1

我正在从 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当进程最终自行终止(并且不会挂起)时不会永远运行。任何指针将不胜感激。

4

2 回答 2

2

为了完整起见,这是我最终使用的代码,使用了建议的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
于 2013-03-19T13:17:31.503 回答
2

尝试signal.alarm在收到每一行后设置一个计时器,然后SIGALRM通过检查自上一行以来是否经过了太多时间来处理。

于 2013-03-17T14:13:02.540 回答