Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keyboard interruptable blocking queue in Python

It seems

import Queue

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

is keyboard interruptible (ctrl-c) whereas

import Queue

Queue.Queue().get()

is not. I could always create a loop;

import Queue
q = Queue()

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

but this seems like a strange thing to do.

So, is there a way of getting an indefinitely waiting but keyboard interruptible Queue.get()?

like image 659
Henrik Gustafsson Avatar asked Oct 17 '08 16:10

Henrik Gustafsson


People also ask

Is Python queue get blocking?

Yep, queue. get() will block only a thread where it was called.

Is queue put thread safe python?

Thread Programming Luckily, Queue() class has a thread-safe implementation with all the required locking mechanism. So producer and consumer from different threads can work with the same queue instance safely and easily.

Does Python have a queue?

Queue is built-in module of Python which is used to implement a queue. queue. Queue(maxsize) initializes a variable to a maximum size of maxsize.

What does queue Put do in Python?

Overview: The method put() adds an element to the queue represented by a Queue instance. The method put() will block if the queue has reached its maximum capacity or executed in blocking mode.


Video Answer


2 Answers

Queue objects have this behavior because they lock using Condition objects form the threading module. So your solution is really the only way to go.

However, if you really want a Queue method that does this, you can monkeypatch the Queue class. For example:

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

This would let you say

q.interruptable_get()

instead of

interruptable_get(q)

although monkeypatching is generally discouraged by the Python community in cases such as these, since a regular function seems just as good.

like image 97
Eli Courtwright Avatar answered Nov 02 '22 19:11

Eli Courtwright


This may not apply to your use case at all. But I've successfully used this pattern in several cases: (sketchy and likely buggy, but you get the point).

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()
like image 29
Anders Waldenborg Avatar answered Nov 02 '22 18:11

Anders Waldenborg