프로그래밍/Python

[python] Exception: task_done() called too many times

채윤아빠 2024. 8. 5. 00:22

Python의 queue.Queue에서 "task_done() called too many times" 오류가 발생하는 이유는 task_done() 메서드를 get()으로 가져온 아이템 수보다 더 많이 호출했기 때문입니다.

발생 원리

Queue는 내부적으로 "처리되지 않은 작업 수(unfinished tasks)"를 카운터로 관리합니다.

  • put()으로 아이템을 넣을 때마다 카운터가 +1
  • task_done()을 호출할 때마다 카운터가 -1
  • 카운터가 0보다 작아지려고 하면 이 오류가 발생

주요 원인들

get() 없이 task_done() 호출

import queue

q = queue.Queue()
q.put("item")
q.task_done()  # get()을 하지 않았는데 task_done() 호출 - 오류!

task_done()을 중복 호출

import queue

q = queue.Queue()
q.put("item")
item = q.get()
q.task_done()
q.task_done()  # 같은 아이템에 대해 두 번 호출 - 오류!
  1. 스레드에서 동기화 문제
import queue
import threading

q = queue.Queue()

def worker():
    while True:
        item = q.get()
        # 작업 처리
        q.task_done()
        q.task_done()  # 실수로 두 번 호출

# 여러 스레드가 동시에 task_done()을 호출하는 경우

올바른 사용법

import queue
import threading

q = queue.Queue()

def worker():
    while True:
        item = q.get()
        if item is None:
            break
        # 작업 처리
        print(f"Processing {item}")
        q.task_done()  # get()한 아이템 하나당 정확히 한 번만 호출

# 작업 추가
for i in range(5):
    q.put(f"task-{i}")

# 워커 스레드 시작
thread = threading.Thread(target=worker)
thread.start()

# 모든 작업 완료 대기
q.join()  # 모든 task_done()이 호출될 때까지 대기

디버깅 팁

  • get()task_done()의 호출 횟수가 정확히 일치하는지 확인
  • 예외 처리 시에도 task_done()이 빠지지 않도록 try-finally 구문 사용
  • 멀티스레딩 환경에서는 각 스레드가 자신이 가져간 아이템에만 task_done()을 호출하도록 주의



728x90
반응형