如何等待信号?

3
我希望能够创建一个while循环,在接收到信号时才继续执行。
例如,在while.py中:
        while queue:
             #wait until signal
             #bla bla

当我在我的Flask服务器上点击按钮时,它应该发送信号给这个循环来继续执行:在main.py中。
         def alarm():
             #trigger loop to continue

有没有一种方法可以做到这一点?
2个回答

1

你需要理解简单的生产者-消费者示例,(查看源代码)

from threading import Thread, Lock
import time
import random

queue = []
lock = Lock()

class ProducerThread(Thread):
    def run(self):
        nums = range(5) #Will create the list [0, 1, 2, 3, 4]
        global queue
        while True:
            num = random.choice(nums) #Selects a random number from list [0, 1, 2, 3, 4]
            lock.acquire()
            queue.append(num)
            print "Produced", num 
            lock.release()
            time.sleep(random.random())


class ConsumerThread(Thread):
    def run(self):
        global queue
        while True:
            lock.acquire()
            if not queue:
                print "Nothing in queue, but consumer will try to consume"
            num = queue.pop(0)
            print "Consumed", num 
            lock.release()
            time.sleep(random.random())


ProducerThread().start()
ConsumerThread().start()

说明:

我们启动了一个生产者线程(以下简称生产者)和一个消费者线程(以下简称消费者)。 生产者不断向队列中添加元素,而消费者则不断从队列中取出元素。 由于队列是共享变量,我们将其放在锁内以避免竞争条件。 当消费者消耗完所有元素且生产者仍在休眠时,消费者尝试继续消耗元素,但由于队列为空,会引发IndexError错误。 但是在每次执行之前,您都会看到打印语句“队列中没有任何东西,但消费者将尝试消耗”,这解释了为什么会出现错误。


这个解决方案不够优雅也是错误的,一个合适的生产者行为是简单地等待项目被添加,而不是引发IndexError - undefined

0
@developer_hatch的time.sleep(random.random())解决方案很差,因为它基于时间引发了一个IndexError,而应该只是简单地等待一会儿。
最好使用Condition对象,它们允许获取锁,然后释放一段时间,直到满足某个条件。
我还建议在可能的情况下使用with语法,以提高可读性并避免忘记释放。
import time
import numpy as np
from threading import Thread, Condition

queue = []
lock = Condition() # Condition, rather than Lock

class Producer(Thread):
  def run(self):
    global queue
    while True:
      time.sleep(np.random.rand())
      task = f'some task {np.random.randint(0, 100)}'
      with lock:
        queue.append(task)
        print(f"Produced: {task}")
        lock.notify() # Notifies other threads the condition might be changed, i.e. `wait`/`wait_for` will get a turn.

class Consumer(Thread):
  def run(self):
    global queue
    while True:
      with lock:
        lock.wait_for(lambda: len(queue) > 0) # Temporarily unlocks, such that other threads alter the condition
        print(f"Consumed: {queue.pop()}")
        time.sleep(np.random.rand())

Producer().start()
Consumer().start()

如果您希望消费者在某个时刻停止,可以让wait_for同时检查一个“完成”条件,例如由生产者设置,或者添加某种特殊的任务,使消费者从while循环中跳出。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接