In Python, `async` and `await` are used to handle asynchronous programming, allowing you to manage and efficiently run potentially blocking operations (like I/O tasks) without blocking the entire program. This is particularly useful for I/O-bound and high-level structured network code.
### Key Concepts:
– **`async def`:** An `async` function is defined using `async def`. It declares that the function contains asynchronous operations and can be used with `await` within its context.
– **`await`:** This keyword is used to pause the function call until the awaited task finishes. It must be used inside an `async` function and allows other tasks to run while waiting for the result of the awaited call.
– **`asyncio`:** This is Python’s built-in library that provides support for asynchronous programming, allowing you to write concurrent code using the `async` and `await` syntax.
### Defining and Running Async Functions
To define an async function and run it, you can use the following basic structure:
“`python
import asyncio
async def main():
await asyncio.sleep(1)
print(“Hello, async world!”)
# Run the main() function
asyncio.run(main())
“`
### Example: Concurrent HTTP Requests
To perform concurrent HTTP requests, you can use `asyncio` along with an HTTP library such as `aiohttp`. Here’s how you can make several HTTP requests concurrently:
“`python
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
‘http://example.com’,
‘http://example.org’,
‘http://example.net’
]
async with aiohttp.ClientSession() as session:
tasks = []
for url in urls:
tasks.append(fetch(session, url))
responses = await asyncio.gather(*tasks)
for response in responses:
print(response[:100]) # Print the first 100 characters of each response
# Run the asynchronous tasks
asyncio.run(main())
“`
### Example: Async Delays
Here’s how you can use `asyncio` to handle delays asynchronously:
“`python
import asyncio
async def say_after(delay, message):
await asyncio.sleep(delay)
print(message)
async def main():
print(‘Start async delays’)
await asyncio.gather(
say_after(2, ‘Hello after 2 seconds’),
say_after(1, ‘Hello after 1 second’),
)
print(‘End async delays’)
# Run the asynchronous tasks
asyncio.run(main())
“`
### Real-World Use Cases
1. **Web Scraping:** Asynchronous programming can significantly speed up web scraping by making concurrent requests to fetch web pages, thereby minimizing the time spent waiting for HTTP responses.
2. **Chat Servers:** In a chat application, handling numerous client requests concurrently is critical. Async I/O allows a single thread to handle multiple connections asynchronously, making it suitable for real-time communication applications.
3. **Microservices Communication:** Applications that rely on microservices can benefit from asyncio as it allows multiple network calls to be made concurrently, reducing the waiting time for service responses.
4. **File I/O Operations:** Asynchronous file handling helps in scenarios where non-blocking access to files is required, especially in server environments where multiple file reads/writes happen concurrently.
In summary, `async` and `await` are powerful tools for writing concurrent programs. They help handle I/O-bound tasks efficiently by allowing other operations to proceed while waiting for external resources, such as network responses or file read/writes. This leads to more responsive applications, particularly in network servers and real-time data processing scenarios.