Consume a queue from both ends with deque
Also published in our Blogger archive.
Consume a queue from both ends with deque
By Batu. AI assistance was used to prepare this article.
collections.deque is a double-ended queue: popleft() removes and returns the leftmost item, while pop() removes and returns the rightmost item. In this recipe, jobs enter on the right, so the leftmost item is also the oldest under that FIFO convention. The later appendleft("hotfix") deliberately breaks that age relationship: a left-side insertion gives priority, not chronological order.
from collections import deque
jobs = deque(["compile", "test", "deploy"])
left_job = jobs.popleft()
right_job = jobs.pop()
jobs.appendleft("hotfix")
jobs.append("package")
assert left_job == "compile"
assert right_job == "deploy"
assert list(jobs) == ["hotfix", "test", "package"]
print(f"left={left_job}")
print(f"right={right_job}")
print(f"remaining={list(jobs)}")
Expected stdout
left=compile
right=deploy
remaining=['hotfix', 'test', 'package']
The output shows two different consumption policies applied to one container: normal work is taken from the left and a tail item can be reclaimed from the right. End appends and pops are approximately constant-time operations, unlike a list.pop(0), which must move later list elements.
An empty deque makes either popleft() or pop() raise IndexError, so a worker that can receive no work must check if jobs: or handle that exception. Also avoid silently using deque(maxlen=...) for lossless work queues: appending to a full bounded deque discards an item at the opposite end. deque does not assign priorities or track timestamps; those rules belong in the values or in a different queue design.
Source: Python deque documentation.