Python中可通过键盘中断的阻塞队列

12 投票
2 回答
3964 浏览
提问于 2025-04-11 09:26

看起来

import Queue

Queue.Queue().get(timeout=10)

是可以通过键盘中断(按ctrl-c)来停止的,而

import Queue

Queue.Queue().get()

则不行。我当然可以创建一个循环;

import Queue
q = Queue()

while True:
    try:
        q.get(timeout=1000)
    except Queue.Empty:
        pass

但这样做似乎有点奇怪。

那么,有没有办法让这个一直等待的Queue.get()也能通过键盘中断呢?

2 个回答

4

这可能跟你的情况没什么关系。不过我在几个场合成功用了这个方法:(虽然有点不靠谱,可能还有bug,但你大概明白我的意思)。

STOP = object()

def consumer(q):
    while True:
        x = q.get()
        if x is STOP:
            return
        consume(x)

def main()
    q = Queue()
    c=threading.Thread(target=consumer,args=[q])

    try:
        run_producer(q)
    except KeybordInterrupt:
        q.enqueue(STOP)
    c.join()
6

Queue对象之所以这样工作,是因为它们使用了来自threading模块的Condition对象进行锁定。所以你的解决方案实际上是唯一可行的方式。

不过,如果你真的想要一个Queue的方法来实现这个功能,你可以对Queue类进行“猴子补丁”。举个例子:

def interruptable_get(self):
    while True:
        try:
            return self.get(timeout=1000)
        except Queue.Empty:
            pass
Queue.interruptable_get = interruptable_get

这样你就可以说

q.interruptable_get()

而不是

interruptable_get(q)

尽管在这种情况下,Python社区通常不鼓励使用猴子补丁,因为一个普通的函数似乎同样有效。

撰写回答