queue — En synkroniserad kö-klass

Källkod: Lib/queue.py


Modulen queue implementerar köer med flera producenter och flera konsumenter. Den är särskilt användbar i trådad programmering när information måste utbytas säkert mellan flera trådar. Klassen Queue i denna modul implementerar all nödvändig låsningssemantik.

Modulen implementerar tre typer av köer, som endast skiljer sig åt i den ordning i vilken posterna hämtas. I en FIFO-kö hämtas de först tillagda uppgifterna först. I en LIFO-kö hämtas den senast tillagda posten först (fungerar som en stapel). Med en prioritetskö hålls posterna sorterade (med hjälp av modulen heapq) och den post som har lägst värde hämtas först.

Internt använder dessa tre typer av köer lås för att tillfälligt blockera konkurrerande trådar, men de är inte utformade för att hantera reentrancy inom en tråd.

Dessutom implementerar modulen en ”enkel” FIFO kötyp, SimpleQueue, vars specifika implementering ger ytterligare garantier i utbyte mot den mindre funktionaliteten.

Modulen queue definierar följande klasser och undantag:

class queue.Queue(maxsize=0)

Konstruktör för en FIFO-kö. maxsize är ett heltal som anger den övre gränsen för hur många objekt som kan placeras i kön. Inmatningen blockeras när denna storlek har uppnåtts, tills köobjekten är förbrukade. Om maxsize är mindre än eller lika med noll är köstorleken oändlig.

class queue.LifoQueue(maxsize=0)

Konstruktör för en LIFO-kö. maxsize är ett heltal som anger den övre gränsen för hur många objekt som kan placeras i kön. Inmatningen blockeras när denna storlek har uppnåtts, tills köobjekten är förbrukade. Om maxsize är mindre än eller lika med noll är köstorleken oändlig.

class queue.PriorityQueue(maxsize=0)

Konstruktor för en prioriterad kö. maxsize är ett heltal som anger den övre gränsen för hur många objekt som kan placeras i kön. Inmatningen kommer att blockeras när denna storlek har uppnåtts, tills köobjekten är förbrukade. Om maxsize är mindre än eller lika med noll är köstorleken oändlig.

De lägst värderade posterna hämtas först (den lägst värderade posten är den som skulle returneras av min(entries)). Ett typiskt mönster för poster är en tupel i formen: (priority_number, data).

Om data-elementen inte är jämförbara kan data förpackas i en klass som ignorerar dataelementet och endast jämför prioritetsnumret:

from dataclasses import dataclass, field
from typing import Any

@dataclass(order=True)
class PrioritizedItem:
    priority: int
    item: Any=field(compare=False)
class queue.SimpleQueue

Konstruktör för en obegränsad FIFO-kö. Enkla köer saknar avancerad funktionalitet som t.ex. uppgiftsspårning.

Tillagd i version 3.7.

exception queue.Empty

Exception uppstår när icke-blockerande get() (eller get_nowait()) anropas på ett Queue-objekt som är tomt.

exception queue.Full

Exception uppstår när icke-blockerande put() (eller put_nowait()) anropas på ett Queue-objekt som är fullt.

exception queue.ShutDown

Exception som uppstår när put() eller get() anropas på ett Queue-objekt som har stängts ner.

Tillagd i version 3.13.

Objekt för köer

Queue-objekt (Queue, LifoQueue eller PriorityQueue) tillhandahåller de publika metoder som beskrivs nedan.

Queue.qsize()

Returnerar den ungefärliga storleken på kön. Observera att qsize() > 0 inte garanterar att en efterföljande get() inte blockeras, och att qsize() < maxsize inte garanterar att put() inte blockeras.

Queue.empty()

Returnerar True om kön är tom, annars False. Om empty() returnerar True garanterar det inte att ett efterföljande anrop till put() inte kommer att blockeras. På samma sätt, om empty() returnerar False garanterar det inte att ett efterföljande anrop till get() inte kommer att blockeras.

Queue.full()

Returnerar True om kön är full, annars False. Om full() returnerar True garanterar det inte att ett efterföljande anrop till get() inte kommer att blockeras. På samma sätt, om full() returnerar False garanterar det inte att ett efterföljande anrop till put() inte kommer att blockeras.

Queue.put(item, block=True, timeout=None)

Lägger in objekt i kön. Om de valfria argen block är true och timeout är None (standard), blockeras vid behov tills en ledig plats finns tillgänglig. Om timeout är ett positivt tal blockeras högst timeout sekunder och Full undantaget uppstår om ingen ledig plats fanns tillgänglig inom den tiden. I annat fall (block är false) läggs ett objekt i kön om en ledig plats omedelbart finns tillgänglig, annars uppstår undantaget Full (timeout ignoreras i det fallet).

Utlöser ShutDown om kön har stängts av.

Queue.put_nowait(item)

Motsvarar put(item, block=False).

Queue.get(block=True, timeout=None)

Tar bort och returnerar ett objekt från kön. Om de valfria argen block är true och timeout är None (standard), blockeras vid behov tills ett objekt är tillgängligt. Om timeout är ett positivt tal blockerar den i högst timeout sekunder och ger upphov till Empty-undantaget om inget objekt var tillgängligt inom den tiden. I annat fall (block är false) returneras ett objekt om ett sådant är omedelbart tillgängligt, annars uppstår undantaget Empty (timeout ignoreras i det fallet).

Före 3.0 på POSIX-system, och för alla versioner på Windows, om block är true och timeout är None, går denna operation in i en oavbruten väntan på ett underliggande lås. Detta innebär att inga undantag kan inträffa, och i synnerhet kommer inte en SIGINT att utlösa ett KeyboardInterrupt.

Utlöser ShutDown om kön har stängts av och är tom, eller om kön har stängts av omedelbart.

Queue.get_nowait()

Motsvarar get(False).

Det finns två metoder för att spåra om uppgifter i kö har bearbetats fullständigt av daemonens konsumenttrådar.

Queue.task_done()

Anger att en tidigare köad uppgift är slutförd. Används av kö-konsumenttrådar. För varje get() som används för att hämta en uppgift, talar ett efterföljande anrop till task_done() om för kön att bearbetningen av uppgiften är klar.

Om en join() för närvarande blockeras kommer den att återupptas när alla objekt har behandlats (vilket innebär att ett task_done()-anrop har mottagits för varje objekt som har put() i kön).

shutdown(immediate=True) anropar task_done() för varje återstående objekt i kön.

Utlöser ett ValueError om den anropas fler gånger än det finns objekt i kön.

Queue.join()

Blockerar tills alla objekt i kön har hämtats och bearbetats.

Antalet oavslutade uppgifter ökar varje gång ett objekt läggs till i kön. Antalet sjunker när en konsumenttråd anropar task_done() för att ange att objektet hämtades och att allt arbete med det är slutfört. När antalet oavslutade uppgifter sjunker till noll avblockeras join().

Exempel på hur man väntar på att uppgifter i kön ska slutföras:

import threading
import queue

q = queue.Queue()

def worker():
    while True:
        item = q.get()
        print(f'Working on {item}')
        print(f'Finished {item}')
        q.task_done()

# Turn-on the worker thread.
threading.Thread(target=worker, daemon=True).start()

# Send thirty task requests to the worker.
for item in range(30):
    q.put(item)

# Block until all tasks are done.
q.join()
print('All work completed')

Avsluta köer

Queue-objekt kan göras så att ytterligare interaktion förhindras genom att de stängs av.

Queue.shutdown(immediate=False)

Stänger av kön, vilket gör att get() och put() ger upphov till ShutDown.

Som standard kommer get() på en avstängd kö inte att aktiveras förrän kön är tom. Sätt immediate till true för att få get() att starta omedelbart istället.

Alla blockerade anropare av put() och get() kommer att avblockeras. Om immediate är true, kommer en uppgift att markeras som utförd för varje återstående objekt i kön, vilket kan avblockera anropare av join().

Tillagd i version 3.13.

SimpleQueue-objekt

SimpleQueue-objekt tillhandahåller de publika metoder som beskrivs nedan.

SimpleQueue.qsize()

Returnerar den ungefärliga storleken på kön. Observera att qsize() > 0 inte garanterar att en efterföljande get() inte blockeras.

SimpleQueue.empty()

Returnerar True om kön är tom, annars False. Om empty() returnerar False garanterar det inte att ett efterföljande anrop till get() inte kommer att blockeras.

SimpleQueue.put(item, block=True, timeout=None)

Lägg in objekt i kön. Metoden blockerar aldrig och lyckas alltid (med undantag för potentiella lågnivåfel som misslyckande med att allokera minne). De valfria argen block och timeout ignoreras och tillhandahålls endast för kompatibilitet med Queue.put().

Denna metod har en C-implementering som är reentrant. Det innebär att ett put()- eller get()-anrop kan avbrytas av ett annat put()-anrop i samma tråd utan att det blir dödläge eller att det interna tillståndet i kön korrumperas. Detta gör den lämplig att använda i destruktorer som __del__ metoder eller weakref callbacks.

SimpleQueue.put_nowait(item)

Motsvarar put(item, block=False), tillhandahålls för kompatibilitet med Queue.put_nowait().

SimpleQueue.get(block=True, timeout=None)

Tar bort och returnerar ett objekt från kön. Om de valfria argen block är true och timeout är None (standard), blockeras vid behov tills ett objekt är tillgängligt. Om timeout är ett positivt tal blockerar den i högst timeout sekunder och ger upphov till Empty-undantaget om inget objekt var tillgängligt inom den tiden. I annat fall (block är false) returneras ett objekt om ett sådant är omedelbart tillgängligt, annars uppstår undantaget Empty (timeout ignoreras i det fallet).

SimpleQueue.get_nowait()

Motsvarar get(False).

Se även

Klass multiprocessing.Queue

En köklass för användning i en multiprocessing-kontext (snarare än multi-threading).

collections.deque är en alternativ implementering av obegränsade köer med snabba atomiska append()- och popleft()-operationer som inte kräver låsning och som även stöder indexering.