프로그래밍/C, C++, Java, Python

Python Queue.shutdown 사용법

포도알77 2026. 7. 13. 16:53

본문 중간의 쿠팡 추천 상품 구매시 쿠팡 파트너스에서 일정액의 수수료를 제공받습니다.

Python Queue.shutdown 사용법

queue.Queue.shutdown()은 작업 큐를 더 이상 늘리지 않고, 남은 항목을 정리하면서 종료 상태로 전환할 때 쓰는 표준 라이브러리 API다. 2026년 7월 13일 확인 기준 Python 3.14.6 공식 문서는 이 메서드와 queue.ShutDown 예외가 Python 3.13에서 추가됐다고 설명한다.

핵심은 세 가지다. 종료 후에는 새 put()이 막히고, 기본 모드에서는 이미 들어 있는 항목을 get()으로 끝까지 꺼낼 수 있으며, immediate=True는 큐를 즉시 비워서 join()의 일반적인 완료 보장을 깨뜨릴 수 있다. 이 글은 그 동작 차이와 실무 판단 기준만 정리한다.

Queue.shutdown은 언제 필요한가?

생산자와 소비자 스레드가 분리된 코드에서는 "더 이상 새 작업은 받지 않되, 이미 받은 작업은 상황에 따라 처리하거나 폐기해야 하는 시점"이 생긴다. Python 3.13 이전에는 이런 종료 신호를 sentinel 값이나 별도 플래그로 직접 설계하는 경우가 많았지만, 이제는 Queue.shutdown()으로 큐 자체를 종료 모드로 바꿀 수 있다.

즉 종료 상태가 큐 객체의 공개 API로 표현된다는 점이 중요하다. 생산자는 실패를 ShutDown 예외로 바로 감지할 수 있고, 소비자는 남은 작업을 정상적으로 비울지 즉시 중단할지 선택할 수 있다.

기본 종료와 즉시 종료는 무엇이 다를까?

항목 shutdown() shutdown(immediate=True)
put() 즉시 차단되고 ShutDown 발생 즉시 차단되고 ShutDown 발생
기존 큐 항목 남은 항목을 get()으로 꺼낼 수 있음 즉시 비워짐
차단된 get() 큐가 완전히 비면 ShutDown 즉시 깨어나 ShutDown
join() 의미 남은 항목에 task_done()이 호출되면 정상 완료 작업이 처리되지 않아도 풀릴 수 있음

대부분의 서비스 종료 루틴에서는 기본값인 immediate=False가 더 보수적이다. 반대로 프로세스 종료 직전처럼 "남은 작업을 버리더라도 빠르게 빠져나와야 한다"는 상황에서만 즉시 종료를 검토하는 편이 맞다.

종료 뒤 put()get()은 어떻게 바뀔까?

Python 3.14.6 queue 문서 기준으로, 종료된 큐에서는 미래의 put() 호출이 모두 ShutDown을 일으킨다. 이미 put()에서 대기 중이던 호출도 깨어나 같은 예외를 받는다.

get()은 종료 방식에 따라 다르다. 기본 종료에서는 남은 항목이 있는 동안은 계속 꺼낼 수 있지만, 큐가 비면 이후 호출에서 ShutDown이 난다. 즉시 종료에서는 큐가 곧바로 비워지므로 대기 중인 소비자도 바로 종료 예외를 받는다.

import queue

q = queue.Queue()
q.put("task-1")
q.shutdown()

print(q.get())  # task-1

try:
    q.get_nowait()
except queue.ShutDown:
    print("queue closed")

이 예시는 기본 종료의 성격을 보여 준다. 남아 있던 항목은 소비할 수 있지만, 비워진 뒤에는 새 작업 큐로 취급되지 않는다.

join()과 함께 볼 때 왜 주의가 필요할까?

Queue.join()은 원래 모든 작업에 대해 task_done()이 호출됐을 때만 풀린다. 그런데 Python 문서는 shutdown(immediate=True)가 큐를 비우고 미완료 작업 수를 줄여서, 실제 작업 처리 없이도 join()을 풀 수 있다고 경고한다.

따라서 join()을 "모든 작업이 끝났다"는 신호로 사용하는 코드라면 즉시 종료를 섣불리 넣으면 안 된다. 이 모드는 "정상 완료"보다 "빠른 중단" 의미에 가깝다.

 

 

sentinel 값 패턴을 바로 대체할 수 있을까?

상황에 따라 다르다. sentinel 값은 소비자에게 "여기서 루프를 끝내라"는 작업 수준 신호를 보내는 방식이고, shutdown()은 큐 자체를 종료 상태로 바꾸는 방식이다. 여러 소비자가 같은 sentinel을 몇 개 받아야 하는지 신경 쓰기 싫다면 shutdown() 쪽이 더 직접적일 수 있다.

반대로 소비자에게 종료 전 마지막 정리 작업을 명시적으로 전달해야 한다면 sentinel이 더 잘 맞는 경우도 있다. 즉 둘 중 하나가 절대적으로 우월하다기보다, 종료 의미를 큐 레벨에서 표현할지 작업 레벨에서 표현할지의 차이다.

어떤 큐에서 쓸 수 있을까?

공식 문서에서 shutdown()Queue, LifoQueue, PriorityQueue 같은 Queue 객체 섹션에 정의돼 있다. 반면 SimpleQueue 섹션에는 이 메서드가 없다. 따라서 현재 코드가 SimpleQueue를 쓰고 있다면 같은 API를 기대하면 안 된다.

실무에서 무난한 사용 기준

  • 작업을 새로 받지 않으면서 이미 들어온 항목은 처리해야 하면 기본 shutdown()을 우선 검토한다.
  • join()을 완료 보장으로 쓰는 코드에서는 immediate=True를 기본값처럼 쓰지 않는다.
  • 종료 후 생산자 쪽 예외 처리를 위해 queue.ShutDown 분기를 명시한다.
  • 현재 큐가 SimpleQueue인지, task tracking이 있는 Queue 계열인지 먼저 확인한다.
  • Python 3.12 이하 호환이 필요하면 이 API를 전제로 설계하지 않는다.

FAQ

Python 3.12 이하에서도 Queue.shutdown()을 쓸 수 있을까?

아니다. Python 공식 문서는 queue.ShutDown 예외와 Queue.shutdown() 메서드가 Python 3.13에서 추가됐다고 명시한다.

기본 종료를 해도 큐에 남은 작업은 처리할 수 있을까?

그렇다. immediate=False에서는 큐가 더 커지지는 않지만, 이미 적재된 항목은 get()으로 계속 꺼낼 수 있다. 다만 큐가 완전히 비면 이후 get()ShutDown을 일으킨다.

immediate=True는 언제 쓰는 편이 맞을까?

남은 작업을 모두 버려도 되는 빠른 중단 상황에서만 검토하는 편이 맞다. Python 문서도 이 모드가 join()의 일반적인 불변식을 깨뜨릴 수 있다고 경고한다.

참고 자료

반응형
페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사