Async Programming
Async Programming
Introduction
In this lesson, you'll learn about async programming in Python. Coming from C#, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In C#, you're familiar with async programming.
Python has its own approach to async programming, which we'll explore step by step.
The Python Way
Let's see how Python handles this concept. Here's a typical example:
import asyncio
import aiohttp
async def fetch_async(url: str) -> str:
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
data = await fetch_async("https://api.example.com")
print(data)
asyncio.run(main())Comparing to C#
Here's how you might have written similar code in C#:
async Task<string> FetchAsync(string url) {
using var client = new HttpClient();
return await client.GetStringAsync(url);
}
async Task Main() {
string data = await FetchAsync("https://api.example.com");
Console.WriteLine(data);
}You may be used to different syntax or behavior.
Python async def replaces C# async Task / async Task<T>
You may be used to different syntax or behavior.
await works identically in both languages
You may be used to different syntax or behavior.
Python's asyncio module is the event loop (like .NET's task scheduler)
You may be used to different syntax or behavior.
asyncio.run() is the entry point — equivalent to calling an async Main
You may be used to different syntax or behavior.
aiohttp replaces HttpClient for async HTTP in Python
Step-by-Step Breakdown
1. async def and await
Python's async/await syntax is virtually identical to C#. The main difference is the return type: Python uses no return type annotation for the coroutine itself.
async Task<int> ComputeAsync() {
await Task.Delay(100);
return 42;
}import asyncio
async def compute_async() -> int:
await asyncio.sleep(0.1) # Task.Delay equivalent
return 422. Running the Event Loop
C# async Main is handled by the runtime. Python requires an explicit asyncio.run() to start the event loop from synchronous code.
// C# async entry point
static async Task Main() {
var result = await ComputeAsync();
Console.WriteLine(result);
}async def main():
result = await compute_async()
print(result)
# Must explicitly run the event loop
asyncio.run(main())
# In Jupyter notebooks or async contexts, just await:
# result = await compute_async()3. Concurrent Execution
C# uses Task.WhenAll for concurrent awaiting. Python uses asyncio.gather().
var results = await Task.WhenAll(
FetchAsync("url1"),
FetchAsync("url2"),
FetchAsync("url3")
);results = await asyncio.gather(
fetch_async("url1"),
fetch_async("url2"),
fetch_async("url3")
)
# results is a list in the same order4. Sync vs Async Libraries
In Python, standard libraries (requests, sqlite3) are synchronous. For async code, use async-compatible alternatives (aiohttp, aiosqlite).
// C# HttpClient is async-first
var text = await client.GetStringAsync(url);# Sync (blocks the event loop — avoid in async code)
import requests
response = requests.get(url) # blocks!
# Async (correct for async contexts)
import aiohttp
async with aiohttp.ClientSession() as s:
async with s.get(url) as r:
text = await r.text()Common Mistakes
When coming from C#, developers often make these mistakes:
- Python async def replaces C# async Task / async Task<T>
- await works identically in both languages
- Python's asyncio module is the event loop (like .NET's task scheduler)
Key Takeaways
- async def + await works just like C# async/await
- asyncio.run(main()) starts the event loop — required at the entry point
- asyncio.gather() replaces Task.WhenAll()
- Use async-compatible libraries (aiohttp) to avoid blocking the event loop