使用 ThreadPoolExecutor 优雅退出

Gracefully exit using ThreadPoolExecutor

当使用 ThreadPoolExecutor 时,如何优雅地退出信号中断?我想拦截一个 SIGINT 并优雅地退出进程。我希望当前 运行 个线程完成,但不再启动,并取消所有待处理的任务。

在 python 3.9 中,ThreadPoolExecutor#shutdown 采用一个 cancel_futures 参数来处理取消等待任务。但是,在 python 3.8 及以下版本中,这必须手动处理。幸运的是我们可以自己使用 the code to do this in python 3.9

import sys
import queue
from concurrent.futures import ThreadPoolExecutor

def exit_threads( executor ):
    print( '\nWrapping up, please wait...' )

    py_version = sys.version_info
    if ( py_version.major == 3 ) and ( py_version.minor < 9 ):
        # py versions less than 3.9
        # Executor#shutdown does not accept
        # cancel_futures keyword
        # manually shutdown
        # code taken from https://github.com/python/cpython/blob/3.9/Lib/concurrent/futures/thread.py#L210
        
        # prevent new tasks from being submitted
        executor.shutdown( wait = False )
        while True:
            # cancel all waiting tasks
            try:
                work_item = executor._work_queue.get_nowait()
                                
            except queue.Empty:
                break
                                
            if work_item is not None:
                work_item.future.cancel()

     else:
           executor.shutdown( cancel_futures = True )
                    
     sys.exit( 0 )


executor = ThreadPoolExecutor( max_workers = 5 )            
signal.signal( 
    signal.SIGINT, 
    lambda sig, frame: exit_threads( executor ) 
)

# run desired code here...