如何强制一个函数和所有的subprocess在Linux上超时?
例如,如何在10秒后强制multiprocessed_func
完成:
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()