Python 调用Event.set()后不会通知threading.Event().wait()

Python 调用Event.set()后不会通知threading.Event().wait(),python,python-multithreading,Python,Python Multithreading,我在使用threading.Event()时遇到了一个非常奇怪的问题,无法理解发生了什么?我一定错过了什么,请你指出一下好吗 我有一个侦听器类,它与信号处理程序共享同一个事件对象,下面是我的简化代码: import threading, time class Listener(object): def __init__(self, event): super(Listener, self).__init__() self.eve

我在使用threading.Event()时遇到了一个非常奇怪的问题,无法理解发生了什么?我一定错过了什么,请你指出一下好吗

我有一个侦听器类,它与信号处理程序共享同一个事件对象,下面是我的简化代码:

import threading, time

class Listener(object):    

    def __init__(self, event):        
        super(Listener, self).__init__()
        self.event = event

    def start(self):                
        while not self.event.is_set():            
            print("Listener started, waiting for messages ...")    
            self.event.wait()

        print("Listener is terminated ...")
        self.event.clear()    

event = threading.Event()

def handler(signum, frame):    
    global event
    event.set()
    print('Signal handler called with signal [%s]' % signum)

if __name__ == "__main__": 
    signal.signal(signal.SIGINT, handler)
    listener = Listener(event)
    listener.start()
在我运行代码之后,我按ctrl+c来中断它,实际上什么都没有发生。如果我想退出,我必须使用kill-9终止进程。但是,如果我向
事件.wait()
提供一个参数,它就起作用了。但它一直在打印:

侦听器已启动,正在等待消息…”

每次都是秒。但它会打印出来:

侦听器已终止

按Ctrl+c键,这就是我想要的

while not self.event.is_set():
        print("Listener started, waiting for messages ...")
        self.event.wait(1)

为什么我必须在
event.wait()
中提供一个timeout参数才能使其响应ctrl+c事件?根据文档,调用
wait()的event.wait()线程
一旦标志为true,就不会阻塞。顺便说一句,我正在使用python 2.7.3。

有几个线程讨论python线程、中断、锁和事件的相关问题

例如,请参见和,但还有更多


python3的情况要好得多,它改进了
wait()
的实现,使其不可中断。

这对您有用吗?基本上,为侦听器启动另一个线程,在主线程等待信号时在那里等待

#!/usr/bin/python
import threading, signal

class Listener(threading.Thread):
    def __init__(self, event):
        super(Listener, self).__init__()
        self.event = event

    def run(self):
        while not self.event.is_set():                                                                                                                                            
            print("Listener started, waiting for messages ...")
            self.event.wait()

        print("Listener is terminated ...")
        self.event.clear()

event = threading.Event()

def handler(signum, frame):
    global event
    event.set()
    print('Signal handler called with signal [%s]' % signum)

if __name__ == "__main__":
    signal.signal(signal.SIGINT, handler)
    listener = Listener(event)
    listener.start()
    while listener.is_alive():
        pass 

以下代码与原始代码类似

差异:

  • 子类化
    线程
    类,使用
    运行
    (vs开始)

  • 使用简单的无超时的
    wait()
    ,这更容易预测

  • 信号处理程序不会直接触发
    事件
    。相反,它只是隐式地唤醒主进程,该进程位于
    signal.pause()

  • 主程序从
    pause()
    唤醒后触发
    Event.set()
    ——主程序将在任何信号上执行此操作,而不仅仅是
    SIGINT
    (control-C)。出于测试目的,两秒钟后会有报警呼叫

  • 希望这有帮助

    来源 输出
    这个链接可能会帮助您-。基本上,它解释了信号是由解释器处理的,而
    event.wait()
    由C函数执行。所以解释器只需等待C函数退出,除非您指定超时,否则不会发生。感谢您指出这一点。这很有帮助。非常感谢Rumple,这确实有效。但单独运行线程可能并不理想。我将只使用self.event.wait(1)但是再次感谢你的帮助。
    import signal, threading, time
    
    class Listener(threading.Thread):
    
        def __init__(self, event):        
            super(Listener, self).__init__()
            self.event = event
    
        def run(self):                
            print("Listener started, waiting for messages ...")    
            while not self.event.wait():
                print('(timeout)')
            print("Listener is terminated ...")
            self.event.clear()    
    
    
    event = threading.Event()
    
    def handler(signum, _frame):    
        # global event
        # event.set()
        print('Signal handler called with signal [%s]' % signum)
    
    if __name__ == "__main__": 
        signal.signal(signal.SIGINT, handler)
        signal.signal(signal.SIGALRM, handler)
        signal.alarm(2)
    
        listener = Listener(event)
        listener.start()
    
        print '* PAUSE'
        signal.pause()              # wait for a signal
    
        print '* SIGNALLING'
        event.set()
        listener.join()
        print('* DONE')
    
    Listener started, waiting for messages ...
    * PAUSE
    Signal handler called with signal [14]
    * SIGNALLING
    Listener is terminated ...
    * DONE