使用^ C/KeyboardInterrupt中断子线程中的Python raw_input() [英] Interrupting Python raw_input() in a child thread with ^C/KeyboardInterrupt

查看:221
本文介绍了使用^ C/KeyboardInterrupt中断子线程中的Python raw_input()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在多线程Python程序中,有时一个线程会使用内置的 raw_input().我希望能够在raw_input提示符下通过在外壳上键入^ C来关闭程序(即,使用SIGINT信号).但是,当子线程正在执行raw_input时,键入^ C不会执行任何操作-直到我按下return(离开raw_input)时,才会引发KeyboardInterrupt.

In a multithreaded Python program, one thread sometimes asks for console input using the built-in raw_input(). I'd like to be able to be able to close the program while at a raw_input prompt by typing ^C at the shell (i.e., with a SIGINT signal). However, when the child thread is executing raw_input, typing ^C does nothing -- the KeyboardInterrupt is not raised until I hit return (leaving raw_input).

例如,在以下程序中:

import threading

class T(threading.Thread):
    def run(self):
        x = raw_input()
        print x

if __name__ == '__main__':
    t = T()
    t.start()
    t.join()

键入^ C直到输入完成后才执行任何操作.但是,如果我们仅调用T().run()(即单线程情况:只需在主线程中运行raw_input),^ C将立即关闭程序.

Typing ^C does nothing until after the input is finished. However, if we just call T().run() (i.e., the single-threaded case: just run raw_input in the main thread), ^C closes the program immediately.

大概是因为SIGINT被发送到主线程,该主线程在控制台上的派生线程阻塞时被挂起(等待GIL).在raw_input返回之后,主线程直到抓住GIL才开始执行其信号处理程序. (如果我错了,请纠正我-我不是Python线程实现的专家.)

Presumably, this is because SIGINT is sent to the main thread, which is suspended (waiting for the GIL) while the forked thread blocks on the console read. The main thread does not get to execute its signal handler until it grabs the GIL after raw_input returns. (Please correct me if I'm wrong about this -- I'm not an expert on Python's threading implementation.)

有没有一种方法可以像标准的raw_input一样从stdin读取,同时允许SIGINT由主线程处理,从而降低了整个过程?

Is there a way to read from stdin in a raw_input-like way while allowing the SIGINT to be handled by the main thread and thus bring down the whole process?

[我已经在Mac OS X和一些不同的Linux上观察到了上述行为.]

[I've observed the behavior above on Mac OS X and a few different Linuxes.]

编辑:我误解了上面的基本问题.在进一步调查中,是对join()的主线程调用阻止了信号处理:Guido van Rossum自己解释说,底层连接中的锁定获取是不间断的.这意味着信号实际上被推迟到整个线程完成为止-因此,这实际上与raw_input完全无关(只是事实是后台线程正在阻塞,因此联接无法完成).

I've mischaracterized the underlying problem above. On further investigation, it's the main thread's call to join() that's preventing signal handling: Guido van Rossum himself has explained that the underlying lock acquire in join is uninterruptible. This means that the signal is actually being deferred until the entire thread finishes -- so this really has nothing to do with raw_input at all (just the fact that the background thread is blocking so that the join does not complete).

推荐答案

在没有超时的情况下调用join时,它是不可中断的,但是在具有超时的情况下调用时,则是可中断的.尝试添加任意超时并将其放入while循环:

When join is called with no timeout, it is uninterruptable, but when it is called with a timeout, it is interruptable. Try adding an arbitrary timeout and putting it in a while loop:

while my_thread.isAlive():
    my_thread.join(5.0)

这篇关于使用^ C/KeyboardInterrupt中断子线程中的Python raw_input()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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