<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nazneen Mulani</title>
    <description>The latest articles on DEV Community by Nazneen Mulani (@nazneen_mulani_0770953dc6).</description>
    <link>https://dev.to/nazneen_mulani_0770953dc6</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3078721%2F98cfb9cf-9bd5-4b40-81a0-8d103fe548a2.jpg</url>
      <title>DEV Community: Nazneen Mulani</title>
      <link>https://dev.to/nazneen_mulani_0770953dc6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nazneen_mulani_0770953dc6"/>
    <language>en</language>
    <item>
      <title>Concurrency in Python</title>
      <dc:creator>Nazneen Mulani</dc:creator>
      <pubDate>Tue, 06 May 2025 06:39:34 +0000</pubDate>
      <link>https://dev.to/nazneen_mulani_0770953dc6/concurrency-in-python-35hl</link>
      <guid>https://dev.to/nazneen_mulani_0770953dc6/concurrency-in-python-35hl</guid>
      <description>&lt;h2&gt;
  
  
  Fundamentals of Concurrency
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs60ete1nmsko9qpv41f4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs60ete1nmsko9qpv41f4.png" alt="Image description" width="504" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Concurrency&lt;/em&gt;&lt;/strong&gt;: Managing multiple tasks simultaneously to improve responsiveness. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Threads and asyncio operate on a single processor, switching tasks. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiprocessing achieves true parallelism by using multiple CPU cores.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Parallelism&lt;/em&gt;&lt;/strong&gt;: Running tasks literally at the same time on different processors. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Types of Tasks&lt;/em&gt;&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I/O-Bound: Limited by input/output operations (e.g., network, file system). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CPU-Bound: Limited by the processor's computational power. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Concurrency Models
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Threading&lt;/em&gt;&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use for I/O-bound tasks. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Managed by the OS (preemptive multitasking). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python module: threading, concurrent.futures.ThreadPoolExecutor. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Asyncio&lt;/em&gt;&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Best for I/O-bound tasks. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uses cooperative multitasking (tasks decide when to yield control). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requires non-blocking libraries (e.g., aiohttp for HTTP requests). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python module: asyncio. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Multiprocessing&lt;/em&gt;&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use for CPU-bound tasks. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Achieves parallelism by using multiple processes. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python module: multiprocessing, concurrent.futures.ProcessPoolExecutor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advantages and Limitations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Threading&lt;/em&gt;&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;✅ Simplifies concurrency for I/O-bound tasks. &lt;/p&gt;

&lt;p&gt;❌ Limited by Python’s Global Interpreter Lock (GIL) for CPU-bound tasks. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Asyncio&lt;/em&gt;&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;✅ Lightweight; excellent for scaling I/O-bound tasks. &lt;/p&gt;

&lt;p&gt;❌ Requires non-blocking libraries; prone to errors if blocking calls are used. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Multiprocessing&lt;/em&gt;&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;✅ Best for CPU-bound tasks; achieves true parallelism. &lt;/p&gt;

&lt;p&gt;❌ Higher overhead for creating processes.  &lt;/p&gt;

&lt;h2&gt;
  
  
  asyncio — Asynchronous I/O
&lt;/h2&gt;

&lt;p&gt;As per &lt;a href="https://docs.python.org/3/library/asyncio.html" rel="noopener noreferrer"&gt;official document&lt;/a&gt; of Python (version 3.13.3 when writing this blog) below are the key concepts to remember when working with asyncio in Python -&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/em&gt;: &lt;br&gt;
asyncio is a library to write concurrent code using the async/await syntax.&lt;br&gt;
asyncio is used as a foundation for multiple Python asynchronous frameworks that provide high-performance network and web-servers, database connection libraries, distributed task queues, etc.&lt;br&gt;
asyncio is often a perfect fit for IO-bound and high-level structured network code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio

async def main():
    print('Guten ...')
    await asyncio.sleep(1)
    print('... morgen!')

asyncio.run(main())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;asyncio provides a set of high-level and low-level APIs to make use of it as a Python developer. &lt;/p&gt;

&lt;p&gt;High level APIs include &lt;strong&gt;Runners, Coroutines and Tasks, Streams, Synchronization Primitives, Subprocesses, Queues, Exceptions&lt;/strong&gt;.&lt;br&gt;
While Low level APIs include &lt;strong&gt;Event Loop, Futures, Transports and, Protocols, Policies, Platform Support, Extending&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;Basic terms to remember -&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AsyncIO Runner&lt;/li&gt;
&lt;li&gt;Event Loop&lt;/li&gt;
&lt;li&gt;Coroutine&lt;/li&gt;
&lt;li&gt;Task Queue&lt;/li&gt;
&lt;li&gt;Future Results&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;AsyncIO Runner&lt;/strong&gt;&lt;br&gt;
This is the outer container that manages the entire async execution&lt;br&gt;
Creates and manages the event loop&lt;br&gt;
Handles setup and cleanup of the async environment&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event Loop&lt;/strong&gt;&lt;br&gt;
The engine that drives asynchronous execution&lt;br&gt;
Continuously runs in cycles, checking for tasks to execute&lt;br&gt;
Manages the scheduling of coroutines&lt;br&gt;
Tracks when I/O operations complete&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coroutine&lt;/strong&gt;&lt;br&gt;
A function marked with async def&lt;br&gt;
Can be paused and resumed using await&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task Queue&lt;/strong&gt;&lt;br&gt;
Where the event loop stores tasks that are ready to run&lt;br&gt;
Manages the order of execution&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Future Results&lt;/strong&gt;&lt;br&gt;
Stores the eventual results of async operations&lt;br&gt;
Used to track completion status&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxtadtg57hw0xwxzy8gz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxtadtg57hw0xwxzy8gz.png" alt="Image description" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Runner API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;asyncio.run(coro, *, debug=None, loop_factory=None)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Execute the coroutine coro and return the result.&lt;/p&gt;

&lt;p&gt;Example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async def main():
    await asyncio.sleep(1)
    print('hey! how are are you?')

asyncio.run(main())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Runner Context Manager API&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;class asyncio.Runner(*, debug=None, loop_factory=None)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;run(coro, *, context=None)&lt;/code&gt;&lt;br&gt;
Run a coroutine coro in the embedded loop&lt;/p&gt;

&lt;p&gt;&lt;code&gt;close()&lt;/code&gt;&lt;br&gt;
Close the runner.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;get_loop()&lt;/code&gt;&lt;br&gt;
Return the event loop associated with the runner instance.&lt;/p&gt;

&lt;p&gt;Example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async def main():
    await asyncio.sleep(1)
    print('hey! whats up?')

with asyncio.Runner() as runner:
    runner.run(main())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Coroutine and Task API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coroutine Function and Coroutine Object&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Define a coroutine function
async def my_function():
    print("Starting")
    await asyncio.sleep(1)
    print("Finished")
    return "Result"

# Call the function - this creates a coroutine object but doesn't run it yet
coro = my_function()
print(type(coro))  # &amp;lt;class 'coroutine'&amp;gt;

# To actually run it, you need to:
# Option 1: Await it (from within another coroutine)
result = await coro

# Option 2: Schedule it on the event loop
task = asyncio.create_task(coro)

# Option 3: Run it using asyncio.run()
result = asyncio.run(coro)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key differences -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Aspect              | Coroutine Function (`async def`)    | Coroutine Object (`func()`)               |
| ------------------- | ----------------------------------- | ----------------------------------------- |
|   Definition        | Declared with `async def`           | Created by calling a coroutine function   |
|   Nature            | A callable                          | An awaitable object                       |
|   Purpose           | Defines an asynchronous operation   | Represents the pending execution          |
|   Execution State   | Static (like a function definition) | Dynamic (has internal state)              |
|   Awaitable?        | ❌ Cannot be awaited                 | ✅ Can be awaited                          |
|   Scheduling        | Not scheduled on event loop         | Can be scheduled with `await` or a `Task` |
|                     |                                     |                                           |

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Event Loop Life cycle Methods&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Explicit event loop management (when asyncio.run() isn't sufficient)
import asyncio

async def my_coroutine():
    await asyncio.sleep(1)
    return "Done"

# Get the event loop
loop = asyncio.get_event_loop()

# Schedule coroutines
task = loop.create_task(my_coroutine())

# Run until all tasks complete
loop.run_until_complete(task)

# Get the result
result = task.result()
print(result)

# Close the loop when done
loop.close()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Creating Tasks API&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio

async def fetch_data(id):
    print(f"Fetching data for {id}...")
    await asyncio.sleep(2)  # Simulating network request
    return f"Data for {id}"

async def main():
    # Create a task that runs in the background
    task = asyncio.create_task(fetch_data(123))

    # Do other work while the task runs concurrently
    print("Doing other work...")
    await asyncio.sleep(1)

    # Wait for the task to complete and get its result
    result = await task
    print(f"Task completed with result: {result}")

asyncio.run(main())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Task Cancellation and Handling Cancellation Exceptions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio

async def long_operation():
    try:
        print("Starting long operation...")
        await asyncio.sleep(10)  # Long operation
        return "Operation completed"
    except asyncio.CancelledError:
        print("Operation was cancelled, cleaning up...")
        # Perform any necessary cleanup
        raise  # Re-raise to propagate cancellation

async def main():
    # Create the task
    task = asyncio.create_task(long_operation())

    # Let it run for a bit
    await asyncio.sleep(2)

    # Cancel the task
    print("Cancelling task...")
    task.cancel()

    try:
        # Await the cancelled task
        await task
    except asyncio.CancelledError:
        print("Main: task was cancelled")

asyncio.run(main())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Task Groups API&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio

async def process_item(item):
    print(f"Processing {item}...")
    await asyncio.sleep(item)  # Variable processing time
    return f"Processed {item}"

async def process_order(order):
    print(f"Processing {order}...")
    await asyncio.sleep(order)  # Variable processing order
    return f"Processed {order}"

async def process_bill(bill):
    print(f"Processing {bill}...")
    await asyncio.sleep(bill)  # Variable processing bill
    return f"Processed {bill}"

async def main():
    # Using TaskGroup to manage multiple tasks
    async with asyncio.TaskGroup() as tg:
        # Create multiple tasks that will run concurrently
        task1 = tg.create_task(process_item(1))
        task2 = tg.create_task(process_order(2))
        task3 = tg.create_task(process_bill(3))

        print("All tasks have been created and are running...")

    # When we exit the TaskGroup context, all tasks are awaited
    # If any task raises an exception, it will be propagated
    print("All tasks completed!")
    print(f"Results: {task1.result()}, {task2.result()}, {task3.result()}")

asyncio.run(main())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How &lt;code&gt;await&lt;/code&gt; suspend execution and yeilds control back to event loop?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio
import time

async def task1():
    print(f"[{time.strftime('%H:%M:%S')}] Task 1 started")
    await asyncio.sleep(2)  # Suspend here, yield to event loop
    print(f"[{time.strftime('%H:%M:%S')}] Task 1 resumed after 2s")
    await asyncio.sleep(1)  # Suspend again
    print(f"[{time.strftime('%H:%M:%S')}] Task 1 completed")

async def task2():
    print(f"[{time.strftime('%H:%M:%S')}] Task 2 started")
    await asyncio.sleep(1)  # Suspend here, yield to event loop
    print(f"[{time.strftime('%H:%M:%S')}] Task 2 resumed after 1s")
    await asyncio.sleep(2)  # Suspend again
    print(f"[{time.strftime('%H:%M:%S')}] Task 2 completed")

async def main():
    # Create tasks to run concurrently
    t1 = asyncio.create_task(task1())
    t2 = asyncio.create_task(task2())

    # Wait for both tasks to complete
    await t1
    await t2

asyncio.run(main())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Program starts
│
├─&amp;gt; Task 1 starts
│   └─&amp;gt; await sleep(2) - Suspends Task 1
│       │
├─&amp;gt; Task 2 starts      (Event loop switches to Task 2)
│   └─&amp;gt; await sleep(1) - Suspends Task 2
│       │
│       │              (Event loop waits, no active tasks)
│       │
│       └─&amp;gt; Task 2 resumes after 1s
│           └─&amp;gt; await sleep(2) - Suspends Task 2 again
│               │
│               └─&amp;gt; Task 1 resumes after 2s
│                   └─&amp;gt; await sleep(1) - Suspends Task 1 again
│                       │
│                       │              (Event loop waits)
│                       │
│                       └─&amp;gt; Task 1 completes
│                           │
│                           └─&amp;gt; Task 2 completes
│
Program ends
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Understanding &lt;code&gt;async with&lt;/code&gt;and &lt;code&gt;async for&lt;/code&gt; Statements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;async with&lt;/code&gt; and &lt;code&gt;async for&lt;/code&gt; are extensions of their synchronous counterparts, designed to work with asynchronous code. &lt;br&gt;
Both are syntactic sugar that make asynchronous code more readable and maintainable by matching the familiar synchronous patterns.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;async with&lt;/code&gt; statement is used with asynchronous context managers, allowing you to handle setup and teardown operations that involve awaitable objects.&lt;/p&gt;

&lt;p&gt;Common for database connections, file operations, network connections&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio

class AsyncResource:
    async def __aenter__(self):
        # Async setup code
        print("Acquiring resource...")
        await asyncio.sleep(1)  # Simulate async acquisition
        print("Resource acquired")
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        # Async cleanup code
        print("Releasing resource...")
        await asyncio.sleep(0.5)  # Simulate async release
        print("Resource released")

    async def use_resource(self):
        print("Using the resource")
        await asyncio.sleep(0.5)

async def main():
    # Using async with to manage the resource
    async with AsyncResource() as resource:
        # This block is executed after __aenter__ completes
        await resource.use_resource()
        # When the block exits, __aexit__ is called automatically

    print("Done with the resource")

asyncio.run(main())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Acquiring resource...
Resource acquired
Using the resource
Releasing resource...
Resource released
Done with the resource
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another Example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio
import aiofiles

async def read_file():
    async with aiofiles.open('data.txt', 'r') as file:
        # File is automatically closed when the block exits
        content = await file.read()
        return content

# Usage
asyncio.run(read_file())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;async for&lt;/code&gt; statement is used with asynchronous iterators, allowing you to iterate over items that are produced asynchronously.&lt;/p&gt;

&lt;p&gt;Common for streaming APIs, paginated results, large dataset processing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio

class AsyncCounter:
    def __init__(self, limit):
        self.limit = limit
        self.counter = 0

    def __aiter__(self):
        return self

    async def __anext__(self):
        if self.counter &amp;lt; self.limit:
            self.counter += 1
            # Simulate async work to produce next value
            await asyncio.sleep(0.5)
            return self.counter
        else:
            # Signal the end of iteration
            raise StopAsyncIteration

async def main():
    # Using async for to iterate over async iterator
    print("Starting iteration...")
    async for number in AsyncCounter(5):
        print(f"Got number: {number}")

    print("Iteration complete")

asyncio.run(main())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Starting iteration...
Got number: 1
Got number: 2
Got number: 3
Got number: 4
Got number: 5
Iteration complete

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another Example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio
import aiohttp

async def fetch_data_stream():
    async with aiohttp.ClientSession() as session:
        async with session.get('https://api.example.com/data', timeout=30) as response:
            # Process the response as a stream
            async for chunk in response.content.iter_chunked(1024):
                # Process each chunk as it arrives
                process_chunk(chunk)

def process_chunk(chunk):
    # Do something with the data chunk
    print(f"Received {len(chunk)} bytes")

# Usage
asyncio.run(fetch_data_stream())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Understanding Futures in AsyncIO&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Futures represent the eventual result of an asynchronous operation&lt;br&gt;
They act as a placeholder until a result is available.&lt;br&gt;
States:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Pending&lt;/code&gt;: Initial state, no result yet&lt;br&gt;
&lt;code&gt;Finished&lt;/code&gt;: Has a result or exception&lt;br&gt;
&lt;code&gt;Cancelled&lt;/code&gt;: Operation was cancelled&lt;/p&gt;

&lt;p&gt;Key Methods:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;set_result(result)&lt;/code&gt;: Set the result of the future&lt;br&gt;
&lt;code&gt;set_exception(exception)&lt;/code&gt;: Set an exception&lt;br&gt;
&lt;code&gt;result()&lt;/code&gt;: Get the result (raises exception if not done)&lt;br&gt;
&lt;code&gt;done()&lt;/code&gt;: Check if completed&lt;br&gt;
&lt;code&gt;add_done_callback(fn)&lt;/code&gt;: Add a callback for when done&lt;/p&gt;

&lt;p&gt;Comparison with Tasks:&lt;/p&gt;

&lt;p&gt;Tasks are higher-level and manage coroutines&lt;br&gt;
Tasks are automatically scheduled to run&lt;br&gt;
Futures are lower-level, must be set manually&lt;br&gt;
Every Task is a Future, but not every Future is a Task&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Awaitable Objects&lt;br&gt;
├── Coroutines (created from async def functions)&lt;br&gt;
├── Tasks (manages coroutines in the event loop)&lt;br&gt;
└── Futures (low-level awaitable objects representing eventual results)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import asyncio

async def set_future_after_delay(future, delay, value):
    # Simulate work
    await asyncio.sleep(delay)
    # Set the result on the future
    future.set_result(value)
    print(f"Future set with value: {value}")

async def main():
    # Create a Future object
    future = asyncio.Future()

    # Schedule a task that will eventually set the future's result
    asyncio.create_task(set_future_after_delay(future, 2, "Future is complete!"))

    print("Waiting for future to complete...")

    # Await the future - this will pause here until the future has a result
    result = await future

    print(f"Received result: {result}")
    print(f"Future state: {future}")

asyncio.run(main())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Waiting for future to complete...
Future set with value: Future is complete!
Received result: Future is complete!
Future state: &amp;lt;Future finished result='Future is complete!'&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Cheat Sheet to save developers valuable time&lt;/strong&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;✅ 1. Fundamental AsyncIO Concepts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Concept                      | Purpose                         | Syntax                                      |
| ---------------------------- | ------------------------------- | ------------------------------------------- |
| Coroutine Function       | Declares async function         | `async def foo():`                          |
| Coroutine Object         | Returned when calling coroutine | `coro = foo()`                              |
| await                   | Suspend and yield control       | `await some_async_func()`                   |
| async with               | Async context manager           | `async with aiofile.open(...) as f:`        |
| async for                | Async iteration (e.g., streams) | `async for line in stream:`                 |
| Event Loop               | Orchestrates async tasks        | `asyncio.run(main())`                       |
| Manual Loop              | Custom control (rare)           | `loop = asyncio.get_event_loop()`           |
| asyncio.run()            | Start main coroutine            | `asyncio.run(main())`                       |
| asyncio.Runner() (3.11+) | Context-managed loop runner     | `with asyncio.Runner() as r: r.run(main())` |
| Event loop policy        | Platform-specific loop rules    | `asyncio.get_event_loop_policy()`           |

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🧵 2. Concurrency Mechanisms&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Tool                  | Purpose                                  | Syntax                                                      |
| --------------------- | ---------------------------------------- | ----------------------------------------------------------- |
| Task              | Wraps coroutine for concurrent execution | `task = asyncio.create_task(coro())`                        |
| Cancel Task       | Stop task                                | `task.cancel()`                                             |
| TaskGroup (3.11+) | Manage related tasks together            | `async with asyncio.TaskGroup() as tg: tg.create_task(...)` |
| Future            | Placeholder for a result                 | `future = asyncio.Future()`                                 |
| Lock              | Mutual exclusion                         | `async with asyncio.Lock():`                                |
| Semaphore         | Limited concurrency                      | `async with asyncio.Semaphore(N):`                          |
| Event             | Wait for/set a signal                    | `await event.wait(); event.set()`                           |
| Queue            | Producer/Consumer coordination           | `await queue.put(x); x = await queue.get()`                 |

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔁 3. Concurrent Execution&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Tool                        | Purpose                               | Syntax                                          |
| --------------------------- | ------------------------------------- | ----------------------------------------------- |
| asyncio.gather()        | Run coroutines concurrently, wait all | `await asyncio.gather(task1, task2)`            |
| asyncio.wait()          | Wait for some/all tasks               | `done, pending = await asyncio.wait(tasks)`     |
| asyncio.as\_completed() | Yield tasks as they complete          | `async for res in asyncio.as_completed(tasks):` |
| asyncio.shield()        | Protect task from cancellation        | `await asyncio.shield(task)`                    |

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🌐 4. Practical I/O&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Operation                 | Purpose                 | Syntax                                              |
| ------------------------- | ----------------------- | --------------------------------------------------- |
| open\_connection()   | Open TCP client         | `reader, writer = await asyncio.open_connection()`  |
| start\_server()       | Start TCP server        | `server = await asyncio.start_server(handler, ...)` |
| StreamReader/Writer   | Read/write via stream   | `data = await reader.read(); writer.write(b'data')` |
| File I/O (workaround) | Use thread executor     | `loop.run_in_executor(None, open, ...)`             |
| aiohttp/httpx         | Async HTTP client       | `await aiohttp.ClientSession().get(url)`            |
| asyncpg               | Async PostgreSQL client | `await asyncpg.connect(...)`                        |

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ 5. Error Handling &amp;amp; Debugging&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Operation                | Purpose                | Syntax                                     |
| ------------------------ | ---------------------- | ------------------------------------------ |
| Try/Except in async  | Catch async exceptions | `try: await foo() except ...`              |
| Propagate Exceptions | Handled in task result | `result = await task`                      |
| Debugging            | Enable debug mode      | `asyncio.get_event_loop().set_debug(True)` |

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In further post, focus would be to on solving problem with asyncio + FastAPI.&lt;/p&gt;

&lt;p&gt;Happy Reading.... 🐍👩🏻‍💻🚀&lt;/p&gt;

</description>
      <category>parallelism</category>
      <category>threading</category>
      <category>multiprocessing</category>
      <category>asyncio</category>
    </item>
  </channel>
</rss>
