2008-10-17 9 views
12

Es scheintKeyboard unterbrechbaren Sperr Warteschlange in Python

import Queue 

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

Tastatur unterbrechbar ist (ctrl-c) während

import Queue 

Queue.Queue().get() 

nicht. Ich könnte immer eine Schleife erstellen;

import Queue 
q = Queue() 

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

aber das scheint wie eine seltsame Sache zu tun.

Also, gibt es eine Möglichkeit, eine unbestimmte Wartezeit zu bekommen, aber die Tastatur unterbrechbar Queue.get()?

+0

Ist der Thread auf andere Weise unterbrechbar? – fatuhoku

+3

Dies ist [Bug 1360] (http://bugs.python.org/issue1360), die als "nicht reparieren" geschlossen wurde. Die vorgeschlagene Problemumgehung besteht darin, immer ein Zeitlimit anzugeben, wenn Sie eine Unterbrechung benötigen. – dimo414

Antwort

6

Queue Objekte haben dieses Verhalten, weil sie mit Condition Objekten aus dem threading-Modul sperren. Ihre Lösung ist also wirklich die einzige Möglichkeit.

Wenn Sie jedoch wirklich eine Queue Methode möchten, die dies tut, können Sie die Queue Klasse monkeypatch. Zum Beispiel:

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

Dies würde sagen wir mal Sie

q.interruptable_get() 

statt

interruptable_get(q) 

obwohl monkeypatching im Allgemeinen durch die Python-Gemeinschaft in Fällen wie diesen, da eine reguläre Funktion wird abgeraten scheint genauso gut zu sein.

+0

Ah, ich sehe, ein schlechter Fall von undichte Abstraktionen *. Ah, gut. * http://www.joelonsoftware.com/articles/LeakyAbstractions.html –

+0

Warum nicht Unterklasse Warteschlange, anstatt Affe Patching es? –

+0

Monkeypatching ist besser, wenn Sie Queue-Objekte empfangen, die durch Code von Drittanbietern instanziiert und zurückgegeben wurden, den Sie nicht ändern können, oder möglicherweise durch den Code eines Mitarbeiters, den Sie ebenfalls nicht ändern können. Vielleicht hätte ich jedoch Unterklassen verwenden sollen, da dies wahrscheinlich nicht sehr häufig ist. –

4

Dies trifft möglicherweise nicht auf Ihren Anwendungsfall zu. Aber ich habe dieses Muster in mehreren Fällen erfolgreich verwendet: (skizzenhaft und wahrscheinlich fehlerhaft, aber Sie bekommen den Punkt).

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()