我正在使用新的 concurrent.futures
模块(也有 Python 2 的移植版)来进行一些简单的多线程 I/O。我在理解如何干净地终止使用该模块启动的任务方面遇到了问题。
请查看以下 Python 2/3 脚本,它重现了我所见到的行为:
#!/usr/bin/env python
from __future__ import print_function
import concurrent.futures
import time
def control_c_this():
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
future1 = executor.submit(wait_a_bit, name="Jack")
future2 = executor.submit(wait_a_bit, name="Jill")
for future in concurrent.futures.as_completed([future1, future2]):
future.result()
print("All done!")
def wait_a_bit(name):
print("{n} is waiting...".format(n=name))
time.sleep(100)
if __name__ == "__main__":
control_c_this()
在运行此脚本时,使用常规的Control-C键盘中断似乎无法干净地终止。我正在OS X上运行。
- 对于Python 2.7,我必须从命令行中使用
kill
来杀死脚本。 Control-C被忽略。 - 在Python 3.4上,如果你按两次Control-C,它就会起作用,但是然后会输出很多奇怪的堆栈跟踪。
我在网上找到的大部分文档都是关于如何使用旧的threading
模块清理其中的线程。但似乎这些文档都不适用于此处。
concurrent.futures
模块提供的所有方法(例如Executor.shutdown()
和Future.cancel()
)只有在Futures尚未启动或已完成时才能起作用,而在这种情况下是没有意义的。 我想立即中断Future。
我的用例很简单:当用户按Control-C时,脚本应该像任何表现良好的脚本一样立即退出。 这就是我想要的全部内容。
那么,使用concurrent.futures
时,正确的获取此行为的方法是什么?