liveBook · Manning

Queue.get_nowait

As explained in Python Concurrency with asyncio

queue.get_nowait is a nonblocking queue method that immediately removes and returns an available item or raises an empty-queue exception.

queue.get_nowait removes and returns an item immediately when one is available. If the queue is empty, it raises an empty-queue exception instead of waiting. This makes it useful when a worker should inspect available work without suspending. section 12.1

Supermarket checkout workers

A checkout worker repeatedly pulls customers with queue.get_nowait(), processes each customer’s products with asynchronous sleeps, and calls queue.task_done() after finishing. Several cashier tasks can therefore process customers concurrently. A worker using await queue.get() instead waits for work when the queue is empty. section 12.1

Listing 12.1 A supermarket checkout queue
import asyncio
from asyncio import Queue
from random import randrange
from typing import List
 
 
class Product:
    def __init__(self, name: str, checkout_time: float):
        self.name = name
        self.checkout_time = checkout_time
 
 
class Customer:
    def __init__(self, customer_id: int, products: List[Product]):
        self.customer_id = customer_id
        self.products = products
 
 
async def checkout_customer(queue: Queue, cashier_number: int):
    while not queue.empty():                                              #1
        customer: Customer = queue.get_nowait()
        print(f'Cashier {cashier_number} '
              f'checking out customer '
              f'{customer.customer_id}')
        for product in customer.products:                                 #2
            print(f"Cashier {cashier_number} "
                  f"checking out customer "
                  f"{customer.customer_id}'s {product.name}")
            await asyncio.sleep(product.checkout_time)
        print(f'Cashier {cashier_number} '
              f'finished checking out customer '
              f'{customer.customer_id}')
        queue.task_done()
 
 
async def main():
    customer_queue = Queue()
 
    all_products = [Product('beer', 2),
                    Product('bananas', .5),
                    Product('sausage', .2),
                    Product('diapers', .2)]
 
    for i in range(10):                                                   #3
        products = [all_products[randrange(len(all_products))]
                    for _ in range(randrange(10))]
        customer_queue.put_nowait(Customer(i, products))
    cashiers = [asyncio.create_task(checkout_customer(customer_queue, i)) #4
                for i in range(3)]                                        #4
    await asyncio.gather(customer_queue.join(), *cashiers)
 
asyncio.run(main())

Inspect the complete supermarket checkout example, including queue creation, cashier tasks, customer processing, and task completion. section 12.1

How Python Concurrency with asyncio covers it

How deep it goes
Defines immediate retrieval and demonstrates it inside workers, while contrasting it with coroutine-based waiting.
Examples
Demonstrates supermarket cashiers removing customers, processing products, and completing queue work.
What you can do after
Apply it via asyncio.Queue to retrieve available work without awaiting queue availability.
How it connects
Connects queue retrieval with asyncio workers, task_done, join, and coroutine scheduling.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Python Concurrency with asyncio. The section links point to the parts of the book it draws on.