Skip to Content
Course content

269: The queue Module: Queue, LifoQueue, PriorityQueue

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Why should I use the queue module instead of just a list or a deque?

This is the first thing most people ask me. If you're just writing a single-threaded script, you're right—a collections.deque is faster and perfectly fine. But the queue module isn't really about the data structure itself; it's about thread safety.

In a multi-threaded app, if two threads try to pop an item from a list at the exact same millisecond, you can end up with a race condition that crashes your program or, worse, silently corrupts your data. The queue module handles all the locking logic under the hood. When you call .put() or .get(), the module ensures that only one thread is touching the internal data at a time. I always tell my juniors: if you have multiple threads producing data and multiple threads consuming it, don't roll your own locking mechanism. Just use queue.

What's the actual difference between Queue, LifoQueue, and PriorityQueue?

It boils down to the order in which you get your data back. I find it easiest to think about these in terms of real-world scenarios:

  • Queue: This is your standard FIFO (First-In, First-Out). Think of it like a line at a coffee shop. The first person to enter the line is the first person served.
  • LifoQueue: This is LIFO (Last-In, First-Out). It's effectively a stack. Imagine a stack of cafeteria trays; the last tray placed on top is the first one someone picks up.
  • PriorityQueue: This ignores the arrival time and looks at a "priority" value. The lowest valued entry gets retrieved first.
from queue import Queue, LifoQueue, PriorityQueue

# Standard FIFO
q = Queue()
q.put("Task 1")
q.put("Task 2")
print(q.get())  # Output: Task 1

# LIFO (Stack)
lq = LifoQueue()
lq.put("Task 1")
lq.put("Task 2")
print(lq.get()) # Output: Task 2

# Priority (Lowest number first)
pq = PriorityQueue()
pq.put((2, "Low priority task"))
pq.put((1, "Urgent task"))
print(pq.get()) # Output: (1, 'Urgent task')

How do I handle priorities if my data isn't just a number?

You'll notice in my example above that I passed a tuple (1, "Urgent task") into the PriorityQueue. That's the secret. The PriorityQueue compares the elements of the tuple in order. It looks at the first element (the integer) to determine priority. If there's a tie, it moves to the second element.

One thing to watch out for: if your second element is something that can't be compared (like a custom class object), and the priority numbers are identical, Python will throw a TypeError because it doesn't know how to "sort" your objects. To get around this, I usually use a three-element tuple: (priority, entry_count, data). The entry_count acts as a tie-breaker so the queue never has to compare the actual data objects.




📋 Practical Task

Exercise: Build a Customer Support Ticket Triage System

You are building a backend system for a support desk. Tickets arrive with different priority levels: 1 for "Critical", 2 for "High", and 3 for "Normal". You need to process these tickets in order of importance, regardless of when they arrived.

Your Task:

  • Create a PriorityQueue to store support tickets.
  • Implement a function add_ticket(priority, customer_name, issue) that pushes a tuple into the queue.
  • Implement a function process_next_ticket() that removes and prints the ticket with the highest priority (the lowest number).
  • Add the following tickets in this exact order:
    • (3, "Alice", "Cannot change profile picture")
    • (1, "Bob", "Database is down!")
    • (2, "Charlie", "Payment gateway timing out")
    • (1, "Daisy", "Security breach detected")
  • Call process_next_ticket() four times and verify that Bob and Daisy (the priority 1s) are handled before Alice and Charlie.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.