如何在Python中不使用join向主线程发送信号?

问题描述 投票:0回答:2

我正在尝试在多线程程序中从子线程向主线程发送信号(不能使用多进程)。不幸的是,即使在用尽了所有在线阅读材料(我可以找到)之后,我仍无法清楚地知道如何做到这一点。我是信号和Python的初学者,所以请耐心听我解释,就像向新手解释一样。 我无法在进程中使用 join 方法,因为我希望两个线程同时运行。 这是我发现与此处主题相关的代码 - http://pymotw.com/2/signal/#signals-and-threads 而且它对我来说真的不起作用。

import signal
import threading
import os
import time

def signal_handler(num, stack):
    print 'Received signal %d in %s' % (num, threading.currentThread())

signal.signal(signal.SIGUSR1, signal_handler)

def wait_for_signal():
    print 'Waiting for signal in', threading.currentThread()
    signal.pause()
    print 'Done waiting'

# Start a thread that will not receive the signal
receiver = threading.Thread(target=wait_for_signal, name='receiver')
receiver.start()
time.sleep(0.1)

def send_signal():
    print 'Sending signal in', threading.currentThread()
    os.kill(os.getpid(), signal.SIGUSR1)

sender = threading.Thread(target=send_signal, name='sender')
sender.start()
sender.join()

# Wait for the thread to see the signal (not going to happen!)
print 'Waiting for', receiver
signal.alarm(2)
receiver.join()

如果可能,请用多线程示例进行解释。 预先感谢!

multithreading python-2.7 signals python-multithreading
2个回答
12
投票

信号和线程真的、真的不能很好地结合在一起。

考虑使用

Event
或其他同步机制。 以下示例创建一个“事件”对象,然后将其传递给两个线程。 一个等待两秒钟,然后示意另一个打印一条消息,然后退出。

来源

import threading, time

def flagger_thread(event):
    """
    wait for two seconds, then make 'event' fire
    """
    time.sleep(2)
    event.set()

def waiter_thread(event):
    print("Waiting for event")
    if event.wait(5):
        print("event set.")
    else:
        print("Timed out.")

stop_event = threading.Event()
threading.Thread(target=flagger_thread, args=[stop_event]).start()
threading.Thread(target=waiter_thread, args=[stop_event]).start()

# wait for all threads to exit
for t in threading.enumerate():
    if t != threading.current_thread():
        t.join()

输出

Waiting for event
event set.

0
投票

问题是你的代码正在做一些与你的目标不同的事情。您的目标是“从子线程向主线程发送信号”,但您发布的示例代码正在监听子线程中的信号。

在您的示例代码中,有三个线程:

  1. 主线程,它调度事物并调用
    alarm(2)
    (如果您只想做
    sleep(2)
    ,通常是一个坏主意)。
  2. 发送信号的
    sender
    子线程。
  3. 等待信号的
    receiver
    子线程。

这是行不通的,因为信号只能从Python的主线程接收。这是一个非常严格的约束。它没有任何可用的星号或“除了……”情况——甚至连诱人的名字

signal.pthread_kill
也没有。

幸运的是,您的目标(处理主线程中的线程发送的信号)很容易实现,如下所示:

import signal
import threading
import os
import time

def signal_handler(num, stack):
    print('Received signal %d in %s' % (num, threading.current_thread()))

signal.signal(signal.SIGUSR1, signal_handler)

def wait_for_signal():
    print('Waiting for signal in', threading.current_thread())
    signal.pause()
    print('Done waiting')
def send_signal():
    time.sleep(1)
    print('Sending signal in', threading.current_thread())
    os.kill(os.getpid(), signal.SIGUSR1)

sender = threading.Thread(target=send_signal, name='sender')
sender.start()
wait_for_signal()
sender.join()  # Optional, but can't hurt
© www.soinside.com 2019 - 2024. All rights reserved.