queue — 동기화된 큐 클래스

queue — 동기화된 큐 클래스

queue 모듈은 다중 생산자, 다중 소비자 큐를 구현해요. 여러 스레드 사이에서 정보를 안전하게 교환해야 하는 스레드 프로그래밍에서 특히 유용해요. 이 모듈의 Queue 클래스는 필요한 모든 잠금 의미를 구현해요.

출처: Python documentation

본문

모듈은 항목을 검색하는 순서만 다른 세 가지 유형의 큐를 구현해요. FIFO 큐에서는 먼저 추가된 작업이 먼저 검색돼요. LIFO 큐에서는 가장 최근에 추가된 항목이 먼저 검색돼요(스택처럼 동작). 우선순위 큐에서는 항목이 정렬된 상태로 유지되고(heapq 모듈 사용) 가장 낮은 값의 항목이 먼저 검색돼요.

내부적으로 이 세 큐 유형은 잠금을 사용해 경쟁하는 스레드를 일시적으로 차단해요. 하지만 한 스레드 내의 재진입(reentrancy)을 처리하도록 설계되진 않았어요.

또한 모듈은 더 적은 기능을 대가로 추가 보장을 제공하는 "단순" FIFO 큐 유형인 SimpleQueue 를 구현해요.

클래스 (Classes)

  • class queue.Queue(maxsize=0) — FIFO 큐 생성자. maxsize 는 큐에 넣을 수 있는 항목 수의 상한을 설정하는 정수예요. 이 크기에 도달하면 큐 항목이 소비될 때까지 삽입이 차단돼요. maxsize 가 0 이하이면 큐 크기는 무한이에요.
  • class queue.LifoQueue(maxsize=0) — LIFO 큐 생성자. 동작 방식은 Queue 와 같되 항목 검색 순서가 다르고, maxsize 0 이하면 무한 크기.
  • class queue.PriorityQueue(maxsize=0) — 우선순위 큐 생성자. 가장 낮은 값 항목이 먼저 검색되고, maxsize 0 이하면 무한 크기.
  • class queue.SimpleQueue — 무한 FIFO 큐 생성자. 단순 큐는 작업 추적 같은 고급 기능이 없어요. 항목 타입에 대해 generic 해요. 버전 3.7 추가.

큐 객체 (Queue Objects)

Queue, LifoQueue, PriorityQueue 객체는 다음 공개 메서드를 제공해요.

  • Queue.qsize() — 큐의 대략적인 크기를 반환해요. qsize() > 0 이 다음 get() 이 차단되지 않음을 보장하진 않고, qsize() < maxsizeput() 이 차단되지 않음을 보장하지도 않아요.
  • Queue.put(item, block=True, timeout=None)item 을 큐에 넣어요. block 이 참이고 timeoutNone(기본)이면 자유 슬롯이 생길 때까지 필요하면 차단해요. timeout 이 양수면 최대 timeout 초 차단하고 그 시간 안에 자유 슬롯이 없으면 Full 예외를 발생시켜요. 그 외(block 거짓)에는 즉시 자유 슬롯이 있으면 항목을 넣고, 없으면 Full 예외를 발생시켜요. 큐가 종료되면 ShutDown 을 발생시켜요.
  • Queue.put_nowait(item)put(item, block=False) 와 동등.
  • Queue.get(block=True, timeout=None) — 큐에서 항목을 제거하고 반환해요. block 이 참이고 timeoutNone 이면 항목이 생길 때까지 필요하면 차단해요. timeout 이 양수면 최대 timeout 초 차단하고 그 안에 없으면 Empty 예외를 발생시켜요. block 이 거짓이면 즉시 항목이 있으면 반환하고 없으면 Empty 예외를 발생시켜요.
  • Queue.task_done() — 이전에 큐에 넣었던 작업이 완료되었음을 나타내요. 큐 소비자 스레드가 사용해요. 작업을 가져오는 각 get() 에 대해 이후의 task_done() 호출이 작업 처리가 완료됐음을 큐에 알려요. 큐에 넣은 항목 수보다 더 많이 호출하면 ValueError 를 발생시켜요.
  • Queue.join() — 큐의 모든 항목이 가져와지고 처리될 때까지 차단해요. 항목이 큐에 추가될 때마다 미완료 작업 수가 증가하고, 소비자 스레드가 task_done() 을 호출해 항목 검색·작업 완료를 나타내면 감소해요. 미완료 작업 수가 0이 되면 join() 이 해제돼요. 그리고 나서 이 작업 반복을 위해 스레드가 시작되고? 예제는 아래를 참고하세요.
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()

threading.Thread(target=worker, daemon=True).start()

for item in range(30):
    q.put(item)

q.join()
print('All work completed')
  • Queue.shutdown(immediate=False)Queue 인스턴스를 종료 모드로 전환해요. immediate 가 거짓(기본)이면 이미 로드된 작업을 추출하는 get() 호출로 큐를 정상적으로 종료할 수 있어요. 남은 각 작업에 task_done() 이 호출되면 대기 중인 join() 이 정상적으로 해제돼요. 큐가 비면 이후 get() 호출은 ShutDown 을 발생시켜요. immediate 가 참이면 즉시 종료돼서 큐가 완전히 비워지고 미완료 작업 수가 줄어들어요. 버전 3.13 추가.

SimpleQueue 객체 (SimpleQueue Objects)

  • SimpleQueue.qsize() — 대략적인 큐 크기 반환.
  • SimpleQueue.empty() — 큐가 비면 True, 아니면 False. empty()False 를 반환해도 다음 get() 이 차단되지 않음을 보장하지 않아요.
  • SimpleQueue.put(item, block=True, timeout=None) — 항목을 큐에 넣어요. 이 메서드는 결코 차단하지 않고 항상 성공해요(잠재적 저수준 오류 예외). blocktimeout 은 무시되며 Queue.put() 과의 호환을 위해 제공돼요. CPython 구현 세부 사항: 이 메서드는 재진입 가능한 C 구현이에요. 즉 같은 스레드에서 put() 또는 get() 호출을 다른 put() 호출로 교란해도 데드락이나 내부 상태 손상이 없어요. 이는 __del__ 메서드나 weakref 콜백 같은 소멸자에서 쓰기에 적합해요.
  • SimpleQueue.put_nowait(item)put(item, block=False) 와 동등.
  • SimpleQueue.get(block=True, timeout=None) — 큐에서 항목을 제거·반환해요. block 이 참이고 timeoutNone 이면 항목이 생길 때까지 차단하고, timeout 이 양수면 최대 그 시간 차단 후 없으면 Empty 를 발생시켜요. block 이 거짓이면 즉시 없으면 Empty 를 발생시켜요.
  • SimpleQueue.get_nowait()get(False) 와 동등.

참고 (See also)

  • multiprocessing.Queue — 멀티스레딩이 아닌 멀티프로세싱 문맥에서 쓰는 큐 클래스.
  • collections.deque — 잠금이 필요 없고 인덱싱도 지원하는 빠른 원자적 append()popleft() 연산을 가진 무한 큐의 대체 구현.

더 알아보기 (Learn more)