如何在 CTRL-C 上停止 ThreadPoolExecutor.map 并退出?
How to stop ThreadPoolExecutor.map and exit on CTRL-C?
python 脚本多次执行 IO 绑定函数(数量级:5000 到 75000 之间的任何值)。通过使用
这仍然是相当高效的
def _iterator(): ... # yields 5000-75000 different names
def _thread_function(name): ...
with concurrent.futures.ThreadPoolExecutor(max_workers=11) as executor:
executor.map(_thread_function, _iterator(), timeout=44)
如果用户按下 CTRL-C,它只会打乱一个线程。我希望它停止启动新线程;并结束当前正在进行的线程或立即杀死它们,无论如何。
我该怎么做?
可能会回答您的问题。
本质上,来自concurrent.futures.Executor.map
的文档
If a func call raises an exception, then that exception will be raised when its value is retrieved from the iterator.
因为您永远不会从 map() 中检索值,所以不会在您的主线程中引发异常。
此外,来自PEP 255
If an unhandled exception-- including, but not limited to, StopIteration --is raised by, or passes through, a generator function, then the exception is passed on to the caller in the usual way, and subsequent attempts to resume the generator function raise StopIteration. In other words, an unhandled exception terminates a generator's useful life.
因此,如果您将代码更改为(注意 for
循环):
def _iterator(): ... # yields 5000-75000 different names
def _thread_function(name): ...
with concurrent.futures.ThreadPoolExecutor(max_workers=11) as executor:
for _ in executor.map(_thread_function, _iterator(), timeout=44):
pass
InterruptedError
将在主线程中引发,并通过生成器 (executor.map(_thread_function, _iterator(), timeout=44)
) 将终止它。
python 脚本多次执行 IO 绑定函数(数量级:5000 到 75000 之间的任何值)。通过使用
这仍然是相当高效的def _iterator(): ... # yields 5000-75000 different names
def _thread_function(name): ...
with concurrent.futures.ThreadPoolExecutor(max_workers=11) as executor:
executor.map(_thread_function, _iterator(), timeout=44)
如果用户按下 CTRL-C,它只会打乱一个线程。我希望它停止启动新线程;并结束当前正在进行的线程或立即杀死它们,无论如何。
我该怎么做?
本质上,来自concurrent.futures.Executor.map
的文档If a func call raises an exception, then that exception will be raised when its value is retrieved from the iterator.
因为您永远不会从 map() 中检索值,所以不会在您的主线程中引发异常。
此外,来自PEP 255
If an unhandled exception-- including, but not limited to, StopIteration --is raised by, or passes through, a generator function, then the exception is passed on to the caller in the usual way, and subsequent attempts to resume the generator function raise StopIteration. In other words, an unhandled exception terminates a generator's useful life.
因此,如果您将代码更改为(注意 for
循环):
def _iterator(): ... # yields 5000-75000 different names
def _thread_function(name): ...
with concurrent.futures.ThreadPoolExecutor(max_workers=11) as executor:
for _ in executor.map(_thread_function, _iterator(), timeout=44):
pass
InterruptedError
将在主线程中引发,并通过生成器 (executor.map(_thread_function, _iterator(), timeout=44)
) 将终止它。