我正在使用新concurrent.futures模块(也具有Python 2反向端口)来执行一些简单的多线程I / O。我在理解如何清除使用此模块开始的任务时遇到麻烦。
concurrent.futures
请查看以下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上运行。
kill
我在网上找到的大多数文档都谈到如何使用旧threading模块彻底杀死线程。这似乎都不适用于这里。
threading
而且,concurrent.futures模块中提供的用于停止事物的所有方法(例如Executor.shutdown()和Future.cancel())仅在期货尚未开始或尚未完成时才起作用,在这种情况下这是没有意义的。我想立即打断未来。
Executor.shutdown()
Future.cancel()
我的用例很简单:当用户点击Control-C时,该脚本应立即退出,就像任何行为良好的脚本一样。这就是我想要的。
那么使用时获得此行为的正确方法是concurrent.futures什么?
有点痛苦。本质上,您的工作线程必须在主线程退出之前完成。除非他们退出,否则您不能退出。典型的解决方法是具有一些全局状态,每个线程可以检查以确定它们是否应该做更多的工作。
这是解释原因的引文。本质上,如果在解释器执行操作时退出线程,则可能会发生不良情况。
这是一个工作示例。请注意,由于子线程的睡眠持续时间,Cc最多需要1秒才能传播。
#!/usr/bin/env python from __future__ import print_function import concurrent.futures import time import sys quit = False def wait_a_bit(name): while not quit: print("{n} is doing work...".format(n=name)) time.sleep(1) def setup(): executor = concurrent.futures.ThreadPoolExecutor(max_workers=5) future1 = executor.submit(wait_a_bit, "Jack") future2 = executor.submit(wait_a_bit, "Jill") # main thread must be doing "work" to be able to catch a Ctrl+C # http://www.luke.maurits.id.au/blog/post/threads-and-signals-in-python.html while (not (future1.done() and future2.done())): time.sleep(1) if __name__ == "__main__": try: setup() except KeyboardInterrupt: quit = True