使用 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...
当使用 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...