一旦期货开始,您如何杀死期货? [英] How do you kill Futures once they have started?

查看:114
本文介绍了一旦期货开始,您如何杀死期货?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用新的 concurrent.futures 模块(该模块还具有Python 2反向端口)来做一些简单的多线程I/O.我无法理解如何彻底终止使用此模块启动的任务.

I am using the new concurrent.futures module (which also has a Python 2 backport) to do some simple multithreaded I/O. I am having trouble understanding how to cleanly kill tasks started using this module.

查看以下Python 2/3脚本,该脚本重现了我所看到的行为:

Check out the following Python 2/3 script, which reproduces the behavior I'm seeing:

#!/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上运行.

While this script is running it appears impossible to kill cleanly using the regular Control-C keyboard interrupt. I am running on OS X.

  • 在Python 2.7上,我必须从命令行使用kill杀死脚本. Ctrl-C只是被忽略.
  • 在Python 3.4上,如果您按两次Control-C,则Control-C可以工作,但随后会丢弃很多奇怪的堆栈跟踪.
  • On Python 2.7 I have to resort to kill from the command line to kill the script. Control-C is just ignored.
  • On Python 3.4, Control-C works if you hit it twice, but then a lot of strange stack traces are dumped.

我在网上找到的大多数文档都谈到如何使用旧的threading模块彻底杀死线程.似乎没有一个适用于此.

Most documentation I've found online talks about how to cleanly kill threads with the old threading module. None of it seems to apply here.

并且concurrent.futures模块中提供的所有用于停止操作的方法(例如Executor.shutdown()Future.cancel())仅在期货尚未开始或尚未完成时才起作用,在这种情况下这是没有意义的.我想立即打断未来.

And all the methods provided within the concurrent.futures module to stop stuff (like Executor.shutdown() and Future.cancel()) only work when the Futures haven't started yet or are complete, which is pointless in this case. I want to interrupt the Future immediately.

我的用例很简单:当用户点击Control-C时,该脚本应立即退出,就像任何行为良好的脚本一样.这就是我想要的.

My use case is simple: When the user hits Control-C, the script should exit immediately like any well-behaved script does. That's all I want.

那么使用concurrent.futures时获得此行为的正确方法是什么?

So what's the proper way to get this behavior when using concurrent.futures?

推荐答案

有点痛苦.本质上,您的工作线程必须在主线程退出之前完成.除非他们退出,否则您不能退出.典型的解决方法是具有一些全局状态,每个线程可以检查以确定它们是否应该做更多的工作.

It's kind of painful. Essentially, your worker threads have to be finished before your main thread can exit. You cannot exit unless they do. The typical workaround is to have some global state, that each thread can check to determine if they should do more work or not.

这是引用解释为什么.本质上,如果在解释器执行操作时退出线程,则可能会发生不良情况.

Here's the quote explaining why. In essence, if threads exited when the interpreter does, bad things could happen.

这是一个可行的例子.请注意,C-c最多需要1秒钟才能传播,因为子线程的睡眠持续时间.

Here's a working example. Note that C-c takes at most 1 sec to propagate because the sleep duration of the child thread.

#!/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

这篇关于一旦期货开始,您如何杀死期货?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆