首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步KeyboardInterrupt和多线程

异步KeyboardInterrupt和多线程
EN

Stack Overflow用户
提问于 2011-11-18 22:34:07
回答 2查看 800关注 0票数 1

多线程程序中的异步信号似乎没有被Python正确处理。但是,我想我应该在这里检查一下,看看有没有人能发现我违反了一些原则,或者误解了一些概念。

我在SO上找到了类似的帖子,但似乎没有一个是完全相同的。

场景是:我有两个线程,读线程和写线程(主线程)。写线程写入读线程轮询的管道。这两个线程是使用threading.Event()原语(我假设它是使用pthread_cond_wait实现的)来协调的。主线程在Event上等待,而读取器线程最终设置它。

但是,如果我想在主线程等待Event时中断程序,就不会异步处理KeyboardInterrupt。

下面是一个小程序来说明我的观点:

代码语言:javascript
复制
#!/usr/bin/python
import os
import sys
import select
import time
import threading

pfd_r = -1
pfd_w = -1
reader_ready = threading.Event()

class Reader(threading.Thread):
    """Read data from pipe and echo to stdout."""
    def run(self):
        global pfd_r
        while True:
            if select.select([pfd_r], [], [], 1)[0] == [pfd_r]:
                output = os.read(pfd_r, 1000)
                sys.stdout.write("R> '%s'\n" % output)
                sys.stdout.flush()
                # Suppose there is some long-running processing happening:
                time.sleep(10)
                reader_ready.set()


# Set up pipe.
(pfd_r, pfd_w) = os.pipe()
rt = Reader()
rt.daemon = True
rt.start()

while True:
    reader_ready.clear()
    user_input = raw_input("> ").strip()
    written = os.write(pfd_w, user_input)
    assert written == len(user_input)
    # Wait for reply -- Try to ^C here and it won't work immediately.
    reader_ready.wait()

使用'./bug.py‘启动程序,并在提示符处输入一些输入。一旦你看到阅读器回复带有前缀'R>',尝试使用^C中断。

我所看到的(Ubuntu Linux10.10,Python2.6.6)是在阻塞reader_ready.wait()返回之后才处理^C。我期望看到的是^C被异步引发,导致程序终止(因为我没有捕捉到KeyboardInterrupt)。

这看起来像是一个人为的例子,但我在一个真实的程序中遇到了这个问题,在这个程序中,time.sleep(10)被实际的计算所取代。

我是不是做错了什么,比如误解了预期的结果是什么?

编辑:我刚刚也测试了Python 3.1.1,同样的问题也存在。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-19 01:51:25

threading._Event对象的wait()方法实际上依赖于thread.lockacquire()方法。但是,thread documentation声明锁的acquire()方法不能被中断,任何KeyboardInterrupt异常都将在锁释放后处理。

因此,基本上,这是预期的工作。实现此行为的线程对象在某些时候(包括队列)依赖于锁,因此您可能希望选择另一条路径。

票数 1
EN

Stack Overflow用户

发布于 2015-06-15 00:14:09

或者,您也可以使用signal模块的pause()函数来代替reader_ready.wait()signal.pause()是一个阻塞函数,当进程接收到信号时,它将被解除阻塞。在您的情况下,当按下^C时,SIGINT SIGINT信号将解除对该功能的阻止。

根据文档,该功能不适用于Windows。我在Linux上对它进行了测试,它可以正常工作。我认为这比使用超时的wait()要好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8184051

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档