Do not use empty() as a guarantee that a later get will succeed immediately. Another consumer can take the item between those calls. Use get_nowait() or a bounded get(timeout=...) and handle Empty.
Check the failure with a small fixture
A consumer checks that a queue has data and then blocks anyway. Make the retrieval decision atomically through the queue API.
from queue import Queue, Empty
q = Queue()
q.put("job-a")
assert not q.empty()
# Simulate a different consumer taking the available item.
assert q.get_nowait() == "job-a"
q.task_done()
try:
q.get_nowait()
except Empty:
print("no item available at retrieval")
q.put("job-b")
item = q.get(timeout=0.1)
try:
assert item == "job-b"
finally:
q.task_done()
q.join()What the result means
This deterministic sequence models the gap between inspection and use without relying on thread scheduling. The empty() result was correct when observed; it did not reserve the item. task_done belongs to a successfully retrieved work item and must not be called for an Empty exception.
Choose the correction for your caller
Choose get_nowait for a consumer that can do something else immediately. Choose a positive timeout when waiting briefly is useful, and handle the timeout according to your worker lifecycle. A temporarily empty queue does not prove every producer has finished. Use an explicit completion protocol, such as one agreed sentinel per consumer, or a shutdown facility supported by your Python version. Decide who acknowledges each sentinel if you also use join.
Limits and the next check
The example uses queue.Queue for threads. multiprocessing.Queue has additional feeder and visibility behavior. Queue.join tracks unfinished task acknowledgments; it does not mean that arbitrary producer threads have exited.
Related: Compare a related data or execution contract.
The embedded Python example was executed as an isolated local script on November 10, 2026 (KST), using Python 3.11.6. It demonstrates the stated boundary; it is not a test of your application or a promise of compatibility with every Python release.