如何在 Linux 上使正在运行的函数及其所有子进程超时?



如何在 Linux 上强制一个函数及其所有子进程超时?

例如,multiprocessed_func怎么可能被迫在 10 秒后完成:

import time
def multiprocessed_func(seconds):
    # Assume this a long running function which uses
    # multiprocessing internally and returns None.
    time.sleep(seconds)
try:
    multiprocessed_func(600)
except:
    print('took too long')

用 psutil 文档,我们可以检查当前进程并在给定时间后终止或终止所有子进程。

def terminate_children(grace_period):
    procs = psutil.Process().children()
    for p in procs:
        p.terminate()
    gone, still_alive = psutil.wait_procs(procs, timeout=grace_period)
    for p in still_alive:
        p.kill()
    raise TimeoutError
try:
    multiprocessed_func(long_run=600)
    time.sleep(10)  # then timeout
    terminate_children(grace_period=2)
except TimeoutError:
    print('timed out')
    pass

完整示例:

import multiprocessing
import time
import psutil
def slow_worker(long_run):
    print('started')
    time.sleep(long_run)
    print('finished')
def multiprocessed_func(long_run):
    jobs = []
    for i in range(5):
        p = multiprocessing.Process(target=slow_worker, args=(long_run,))
        jobs.append(p)
        p.start()
        print('starting', p.pid)
def on_terminate(proc):
    print('terminating {}, exit code {}'.format(proc, proc.returncode))
def terminate_children(grace_period):
    procs = psutil.Process().children()
    for p in procs:
        p.terminate()
    gone, still_alive = psutil.wait_procs(procs, timeout=grace_period, 
                                          callback=on_terminate)
    for p in still_alive:
        p.kill()
    raise TimeoutError
try:
    multiprocessed_func(long_run=600)
    time.sleep(10)
    terminate_children(grace_period=2)
except TimeoutError:
    print('timed out')
    pass

如果终止当前进程中的所有子进程过多,因为当前进程中还有其他多处理方法需要保留,那么我们可以multiprocessed_func包装在另一个进程中。

def safe_run(timeout, grace_period):
    try:
        multiprocessed_func(long_run=600)
        time.sleep(timeout)
        terminate_children(grace_period)
    except TimeoutError:
        pass
timeout, grace_period = 10, 2
p = multiprocessing.Process(target=safe_run, args=(timeout, grace_period,))
p.start()
p.join()
p.terminate()
time.sleep(2)
if p.is_alive():
    p.kill()

相关内容

  • 没有找到相关文章

最新更新