-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
269: The queue Module: Queue, LifoQueue, PriorityQueue
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
PriorityQueueto 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.
There are no comments for now.