🔃Unit 3: Concurrency
Last updated
Last updated
async
and await
are key concepts in Python that facilitate writing asynchronous code. They were introduced in Python 3.5 and have become central in writing efficient and non-blocking code, especially in the context of I/O-bound and high-level structured network code.
Synchronous programming is simpler and more straightforward, best suited for linear tasks and CPU-bound operations. Asynchronous programming, on the other hand, allows for concurrent operations, making it ideal for tasks that involve waiting for external operations, thus improving efficiency and scalability in specific scenarios like web servers and UI applications.
Sequential Execution
In synchronous programming, tasks are executed one after another. Each task must complete before the next one starts. This is a straightforward and intuitive way of writing code.
Concurrent Execution
Asynchronous programming allows multiple tasks to be processed concurrently. It enables a task to be paused (usually I/O operations) and resume only when the result is ready, without blocking the execution of other tasks.
Blocking Operations
If a task involves waiting (e.g., for file I/O, network requests), the entire program is blocked or waits until the operation completes. This can lead to inefficiency, especially in I/O-bound applications.
Non-Blocking Operations
In async programming, the program can continue to run other tasks while waiting for other operations to complete. This is especially beneficial for I/O-bound and high-level structured network code.
Ease of Understanding
Because of its sequential nature, synchronous code is generally easier to understand and debug. The flow of control is linear and predictable.
Complexity
Writing and understanding asynchronous code can be more complex than synchronous code. It requires handling of callbacks, promises, or async/await patterns, which can be less intuitive.
Use Cases
Synchronous programming is well-suited for tasks that are CPU-bound or when tasks need to be executed in a specific order without any requirement for scaling.
Use Cases
Asynchronous programming is ideal for applications that require high scalability and responsiveness, such as web servers, UI applications, and networked programs.
Key differences:
Blocking vs. Non-Blocking: Synchronous programming is blocking, while asynchronous programming is non-blocking.
Control Flow: Synchronous code has a straightforward, top-to-bottom control flow. Asynchronous code, however, can be more complex due to callbacks and event loops.
Scalability: Asynchronous programming is more scalable, particularly for I/O-bound and network-bound operations.
Resource Utilization: Asynchronous programming can make better use of system resources, while synchronous programming may underutilize resources during wait times.
async
/await
Keywordsasync
KeywordIn Python, the async
keyword is used to declare a function as an "asynchronous function." Such functions, known as "async functions," are able to "pause" their execution without blocking the entire thread by yielding control back to the event loop.
An async function defines a "coroutine" which is a type of function that can suspend its execution before reaching return
, and it can indirectly pass control back to the event loop. This suspension of execution is done using the await
keyword.
await
KeywordWithin an async function, you use the await
keyword before a function that returns an "awaitable" object (like another async function). This tells Python to pause the async function until the awaitable is resolved. This pause is non-blocking; it allows other async functions to run in the meantime.
When an async function hits an await
keyword, it pauses and yields control back to the event loop, which can then go on to execute other tasks. Once the awaited operation is completed, the event loop resumes the execution of the async function from the point it was paused. In other words, Python will know that it can go and do something else in the meanwhile (like receiving another request).
For await
to work, it has to be inside a function that supports this asynchronicity. To do that, you just declare it with async def
.