Python
Completed
-
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
208: Introduction to asyncio
Imagine you're a barista at a busy coffee shop. You have a customer who wants a latte. To make it, you start the espresso machine, but the machine takes 30 seconds to pull the shot. Now, you have a choice: you can stand there and stare at the machine for 30 seconds, doing absolutely nothing, or you can take the next customer's order while the coffee is dripping.
If you stare at the machine, you're working "synchronously." You're blocked until that one task finishes. If you take other orders, you're working "asynchronously." You've initiated a task that takes time, and instead of wasting your life waiting for it, you switch to something else until the machine "dings" to let you know it's done. This is exactly what asyncio does for your Python code.
Stopping the Stare-Down
In standard Python, when you call a function that fetches data from a website, your whole program freezes. It just sits there. If you have to fetch data from ten different websites, and each takes one second, your program takes ten seconds. That's a lot of staring at the espresso machine.
With asyncio, we tell Python: "This task is going to involve waiting. Go ahead and do other things, and come back to this when the data actually arrives."
Turning Functions into Coroutines
To do this, we change how we define our functions. We use async def instead of just def. This creates a "coroutine." If you try to call a coroutine like a normal function, you'll notice it doesn't actually run the code inside—it just returns a coroutine object. I've seen plenty of developers get frustrated here, thinking their code is broken, but it's actually just Python asking you how you intend to schedule this task.
import asyncio
async def brew_coffee():
print("Starting the espresso machine...")
# This is where the 'waiting' happens
await asyncio.sleep(1)
print("Coffee is ready!")
# This won't work: brew_coffee()
# You need an event loop to run it:
asyncio.run(brew_coffee())
The Magic of the Await Keyword
The await keyword is the most important part of this whole puzzle. It's you, the barista, saying: "I'm pausing this specific task here because I'm waiting on something. Feel free to go do other work."
You can only use await inside an async function. When Python hits an await line, it pauses the execution of that function and jumps back to the event loop to see if any other tasks are ready to make progress.
Handling a Crowd with Gather
Running one async function is fine, but the real power comes when you have a dozen tasks. If you just await them one by one, you're back to square one—you're still waiting for the first coffee to finish before you even start the second one. To actually run them concurrently, we use asyncio.gather().
Check out the difference here. We're simulating fetching data from three different API endpoints:
import asyncio
import time
async def fetch_data(source, delay):
print(f"Fetching from {source}...")
await asyncio.sleep(delay)
print(f"Finished {source} after {delay}s")
return f"{source} data"
async def main():
start_time = time.perf_counter()
# This schedules all three calls to start at roughly the same time
results = await asyncio.gather(
fetch_data("Users-API", 2),
fetch_data("Products-API", 1),
fetch_data("Orders-API", 1.5)
)
end_time = time.perf_counter()
print(f"Results: {results}")
print(f"Total time elapsed: {end_time - start_time:.2f} seconds")
asyncio.run(main())
Notice that the total time isn't 4.5 seconds (2 + 1 + 1.5). It's only 2 seconds—the length of the longest task. Python started the Users-API call, hit the await, immediately jumped to start the Products-API call, hit the await, and so on. It's effectively multitasking.
📋 Practical Task
Build an Asynchronous Website Status Checker
Your task is to build a script that checks the "health" of multiple simulated servers. Since we don't want to actually spam real websites, you'll simulate the network latency using asyncio.sleep().
Requirements:
- Create an
asyncfunction calledcheck_server(server_name, response_time). It should print "Checking [server_name]...", wait for theresponse_time, and then return a string saying "[server_name] is UP". - Create a
maincoroutine that usesasyncio.gatherto check the following servers simultaneously:- "Auth-Server" (takes 1.2 seconds)
- "Database-Cluster" (takes 0.5 seconds)
- "Payment-Gateway" (takes 2.0 seconds)
- "Cache-Layer" (takes 0.8 seconds)
- Print the final list of results and the total time the script took to run.
- Verify that the total elapsed time is approximately 2 seconds, not the sum of all response times.
There are no comments for now.