运行过程中,杀死它,如果它没有在一小时内结束(Run a process and kill it i

2019-07-04 04:16发布

我需要做在Python以下。 我想生成一个进程,和(子模块):

  • 如果进程正常结束,正好从它结束的那一刻继续;
  • 如果,否则,进程“卡”和(说)一小时内不会终止,将其杀死并继续(可能给它的另一个尝试,在一个循环中)。

什么是实现这一目标的最优雅的方式?

Answer 1:

subprocess模块将成为你的朋友。 启动过程中得到一个Popen对象,然后将它传递给这样的功能。 请注意,这只是提高了对超时异常。 如果需要,你可以捕获该异常并调用kill()的方法Popen过程。 (杀是在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)


Answer 2:

至少有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
>>>


Answer 3:

我有一个类似的问题,发现这个答案。 只是为了完整性,我想添加另一种方式是如何的给定时间后终止挂起的进程:蟒蛇信号库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

既然你想反正产生新的进程,这可能不是问题的最佳soloution,虽然。



Answer 4:

一个漂亮的,被动的,方式也使用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()

如果进程在时间结束时,等待()结束,代码继续在这里,取消()停止计时器。 如果同时定时器溢出,并在一个单独的线程执行kill_proc,等待()也将在这里继续和取消()不会做任何事情。 通过RCODE的价值,你就会知道,如果我们timeouted与否。 简单kill_proc:(当然,你可以做任何额外的东西在那里)

def kill_proc(self):
    os.kill(self.p, signal.SIGTERM)


Answer 5:

Koodos彼得Shinners他约好的建议subprocess模块。 我使用exec()之前,并没有对运行时间,尤其是终止它的任何控制。 我对这样的任务最简单的模板下面,我只是使用的超时参数subprocess.run()函数来监视运行时间。 当然,你可以得到标准输出和错误,以及如果需要的话:

from subprocess import run, TimeoutExpired, CalledProcessError

for file in fls:
    try:
        run(["python3.7", file], check=True, timeout=7200)  # 2 hours timeout
        print("scraped :)", file)
    except TimeoutExpired:
        message = "Timeout :( !!!"
        print(message, file)
        f.write("{message} {file}\n".format(file=file, message=message))
    except CalledProcessError:
        message = "SOMETHING HAPPENED :( !!!, CHECK"
        print(message, file)
        f.write("{message} {file}\n".format(file=file, message=message))



文章来源: Run a process and kill it if it doesn't end within one hour