python LogoQueue Management + Python's `queue` module

Queue management refers to the process of handling and organizing items (data, tasks, messages) in a 'queue' data structure. A queue is a linear data structure that follows the First-In, First-Out (FIFO) principle, meaning the first element added to the queue will be the first one to be removed. It's analogous to a line of people waiting for a service – the person who arrives first is served first.

Key characteristics and operations of a queue:
1. Enqueue (put): Adding an item to the rear (end) of the queue.
2. Dequeue (get): Removing an item from the front (beginning) of the queue.
3. Peek/Front: Viewing the item at the front without removing it.
4. isEmpty: Checking if the queue contains any items.
5. Size: Getting the number of items currently in the queue.

Queues are fundamental in computer science and are used in various applications, including:
- Task Scheduling: Operating systems use queues to manage processes waiting for CPU time.
- Message Passing: In concurrent programming, queues allow different threads or processes to communicate by sending and receiving messages.
- Buffering: Managing data flow between systems with different processing speeds.
- Breadth-First Search (BFS): An algorithm used for traversing or searching tree or graph data structures.
- Printer Spooling: Documents waiting to be printed are typically held in a queue.

Python provides a `queue` module (and `collections.deque` for more efficient double-ended queue operations) that offers several types of queues suitable for concurrent and multi-threaded programming:
- `queue.Queue`: A basic FIFO queue.
- `queue.LifoQueue`: A Last-In, First-Out (LIFO) queue, essentially a stack.
- `queue.PriorityQueue`: A queue that retrieves entries based on their priority (lowest priority value is retrieved first).

Example Code

import queue
import threading
import time

 --- 1. Basic FIFO Queue (queue.Queue) ---
print("\n--- FIFO Queue Example ---")
q_fifo = queue.Queue()

 Enqueue items
q_fifo.put("Task A")
q_fifo.put("Task B")
q_fifo.put("Task C")

print(f"Queue size: {q_fifo.qsize()}")

 Dequeue items
print(f"Processing: {q_fifo.get()}")  Task A
print(f"Processing: {q_fifo.get()}")  Task B

print(f"Queue size after processing: {q_fifo.qsize()}")

 Check if empty
print(f"Is queue empty? {q_fifo.empty()}")

q_fifo.get()  Task C
print(f"Is queue empty after last get? {q_fifo.empty()}")


 --- 2. LIFO Queue (queue.LifoQueue) - Acts like a Stack ---
print("\n--- LIFO Queue Example (Stack) ---")
q_lifo = queue.LifoQueue()

q_lifo.put("Item 1")
q_lifo.put("Item 2")
q_lifo.put("Item 3")

print(f"LIFO Queue size: {q_lifo.qsize()}")
print(f"Last in, first out: {q_lifo.get()}")  Item 3
print(f"Last in, first out: {q_lifo.get()}")  Item 2


 --- 3. Priority Queue (queue.PriorityQueue) ---
print("\n--- Priority Queue Example ---")
q_priority = queue.PriorityQueue()

 Items are tuples: (priority_number, data)
 Lower priority_number means higher priority
q_priority.put((3, "Low Priority Task"))
q_priority.put((1, "High Priority Task"))
q_priority.put((2, "Medium Priority Task"))

print(f"Priority Queue size: {q_priority.qsize()}")
print(f"Processing: {q_priority.get()}")  (1, 'High Priority Task')
print(f"Processing: {q_priority.get()}")  (2, 'Medium Priority Task')


 --- 4. Queue with multiple threads (Producer-Consumer pattern) ---
print("\n--- Multi-threaded Queue Example (Producer-Consumer) ---")
shared_queue = queue.Queue(maxsize=5)  Max 5 items

def producer():
    for i in range(1, 10):
        try:
            print(f"Producer: Trying to put item {i}...")
            shared_queue.put(f"Item {i}", timeout=1)  Block if queue is full
            print(f"Producer: Put Item {i}. Queue size: {shared_queue.qsize()}")
            time.sleep(0.5)
        except queue.Full:
            print(f"Producer: Queue is full, skipping item {i}.")
    print("Producer finished.")

def consumer():
    while True:
        try:
            item = shared_queue.get(timeout=2)  Block if queue is empty
            print(f"Consumer: Got {item}. Queue size: {shared_queue.qsize()}")
            shared_queue.task_done()  Mark task as done
            time.sleep(1)
        except queue.Empty:
            print("Consumer: Queue is empty, exiting.")
            break
    print("Consumer finished.")

producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer)

producer_thread.start()
consumer_thread.start()

producer_thread.join()
consumer_thread.join()

print("All threads finished. Example complete.")