π Chapter 2: *Asyncio Basics* π
Chapter 2 delves into the foundational aspects of asyncio in Python, focusing on how it enables single-threaded concurrency using coroutines, tasks, and event loops. Hereβs a breakdown:
π 2.1 Introducing Coroutines
- Coroutines are special Python functions that can pause and resume execution when encountering a potentially long-running task.
- When a coroutine pauses to wait for an operation, other tasks can run concurrently, providing concurrency. π‘
- `async` and `await` are the two essential keywords:
-
-
βοΈ Example of Creating a Coroutine
This is similar to a normal Python function but can pause its execution.
β³ 2.2 Introducing Long-Running Coroutines with `sleep`
- Asyncioβs
- When
βοΈ Example of Using
This coroutine pauses for 1 second before returning "Hello World!". During that second, other coroutines can run concurrently.
π 2.3 Running Concurrently with Tasks
- A task is a wrapper around a coroutine that schedules it to run on the event loop π.
- Tasks allow coroutines to be run concurrently, as they donβt block the event loop, unlike
βοΈ Example of Creating a Task
Here, the task
β 2.4 Canceling Tasks and Setting Timeouts
- Tasks can be canceled using
βοΈ Example of Cancelling a Task
πΌ 2.5 Tasks, Coroutines, Futures, and Awaitables
- Futures represent a value that will be available in the future but might not exist yet. They are used internally in asyncio and can be awaited π―.
- Coroutines and tasks can both be used in
βοΈ Example of Working with Futures
β±οΈ 2.6 Measuring Coroutine Execution Time with Decorators
- By using decorators, we can measure the execution time of coroutines for performance analysis. β
β οΈ 2.7 Pitfalls of Coroutines and Tasks
- Be cautious with CPU-bound code inside coroutines, as it will block the event loop.
- Avoid using blocking I/O APIs; use asyncio-compatible libraries to ensure the event loop runs smoothly π οΈ.
π§ 2.8 Accessing and Manually Managing the Event Loop
- You can access the event loop directly using
π οΈ 2.9 Using Debug Mode
- Debug mode helps in identifying long-running coroutines or tasks that block the event loop π§. You can enable it with:
Or by setting the
βοΈ Example of Running in Debug Mode
#PythonConcurrencyWithAsyncio
#Chapter_02
#Notes #Book
Chapter 2 delves into the foundational aspects of asyncio in Python, focusing on how it enables single-threaded concurrency using coroutines, tasks, and event loops. Hereβs a breakdown:
π 2.1 Introducing Coroutines
- Coroutines are special Python functions that can pause and resume execution when encountering a potentially long-running task.
- When a coroutine pauses to wait for an operation, other tasks can run concurrently, providing concurrency. π‘
- `async` and `await` are the two essential keywords:
-
async defines a function as a coroutine.-
await pauses the coroutine until a result is available from an asynchronous operation.βοΈ Example of Creating a Coroutine
async def my_coroutine() -> None:
print("Hello world!")
This is similar to a normal Python function but can pause its execution.
β³ 2.2 Introducing Long-Running Coroutines with `sleep`
- Asyncioβs
sleep function allows us to pause execution, simulating real-world, long-running operations like web requests or database queries π.- When
await asyncio.sleep() is called, other tasks can be executed during the pause.βοΈ Example of Using
asyncio.sleepasync def hello_world_message() -> str:
await asyncio.sleep(1)
return "Hello World!"
This coroutine pauses for 1 second before returning "Hello World!". During that second, other coroutines can run concurrently.
π 2.3 Running Concurrently with Tasks
- A task is a wrapper around a coroutine that schedules it to run on the event loop π.
- Tasks allow coroutines to be run concurrently, as they donβt block the event loop, unlike
await, which pauses until a result is returned.βοΈ Example of Creating a Task
import asyncio
from util import delay
async def main():
task = asyncio.create_task(delay(3))
await task
Here, the task
delay(3) runs concurrently, while other code can execute.β 2.4 Canceling Tasks and Setting Timeouts
- Tasks can be canceled using
task.cancel(), raising a CancelledError within the task. If a task is taking too long, we can also set timeouts using asyncio.wait_for π.βοΈ Example of Cancelling a Task
async def cancel_task(task):
task.cancel()
try:
await task
except asyncio.CancelledError:
print("Task was cancelled")
πΌ 2.5 Tasks, Coroutines, Futures, and Awaitables
- Futures represent a value that will be available in the future but might not exist yet. They are used internally in asyncio and can be awaited π―.
- Coroutines and tasks can both be used in
await expressions.βοΈ Example of Working with Futures
from asyncio import Future
my_future = Future()
my_future.set_result(42)
print(my_future.result()) # Outputs: 42
β±οΈ 2.6 Measuring Coroutine Execution Time with Decorators
- By using decorators, we can measure the execution time of coroutines for performance analysis. β
β οΈ 2.7 Pitfalls of Coroutines and Tasks
- Be cautious with CPU-bound code inside coroutines, as it will block the event loop.
- Avoid using blocking I/O APIs; use asyncio-compatible libraries to ensure the event loop runs smoothly π οΈ.
π§ 2.8 Accessing and Manually Managing the Event Loop
- You can access the event loop directly using
asyncio.get_event_loop(), though asyncio.run() is recommended for running main coroutines.π οΈ 2.9 Using Debug Mode
- Debug mode helps in identifying long-running coroutines or tasks that block the event loop π§. You can enable it with:
python3 -X dev program.py
Or by setting the
PYTHONASYNCIODEBUG environment variable.βοΈ Example of Running in Debug Mode
asyncio.run(main(), debug=True)
#PythonConcurrencyWithAsyncio
#Chapter_02
#Notes #Book
β€3π2