DEV Community

qing
qing

Posted on

Async Python: The Complete Beginner Guide With Real Examples

Async Python: The Complete Beginner Guide With Real Examples

Async Python: The Complete Beginner Guide With Real Examples

Asynchronous programming is a powerful tool in Python that allows your code to perform multiple tasks concurrently, improving the overall performance and responsiveness of your application. In this tutorial, we will explore the basics of async/await, the event loop, and asyncio.gather, and compare synchronous vs asynchronous HTTP fetching using the httpx library.

Introduction to Async/Await

Async/await is a syntax sugar on top of coroutines, which are special types of functions that can suspend and resume their execution at specific points. The async keyword is used to define a coroutine, and the await keyword is used to suspend the execution of the coroutine until the awaited task is complete.

Here's a simple example of an async function:

import asyncio

async def hello_world():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

async def main():
    await hello_world()

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

In this example, the hello_world function is defined as an async function, and it uses the await keyword to suspend its execution for 1 second using asyncio.sleep(1). The main function is also defined as an async function, and it calls hello_world using the await keyword.

Event Loop

The event loop is the core of the asyncio library, and it's responsible for managing the execution of coroutines. The event loop runs in an infinite loop, checking for new tasks to run and switching between them as needed.

You can create an event loop using asyncio.get_event_loop() and run it using loop.run_until_complete(). However, in most cases, you can simply use asyncio.run() to run your async code.

import asyncio

async def hello_world():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

loop = asyncio.get_event_loop()
loop.run_until_complete(hello_world())
Enter fullscreen mode Exit fullscreen mode

Asyncio.Gather

asyncio.gather is a function that allows you to run multiple coroutines concurrently and wait for all of them to complete. It returns a list of results, which can be accessed using the await keyword.

Here's an example of using asyncio.gather to run multiple tasks concurrently:

import asyncio

async def task1():
    await asyncio.sleep(1)
    return "Task 1"

async def task2():
    await asyncio.sleep(2)
    return "Task 2"

async def main():
    tasks = [task1(), task2()]
    results = await asyncio.gather(*tasks)
    print(results)

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

In this example, task1 and task2 are defined as async functions, and they simulate some I/O-bound work using asyncio.sleep(). The main function creates a list of tasks and uses asyncio.gather to run them concurrently. The results are then printed to the console.

Sync vs Async HTTP Fetching with Httpx

The httpx library is a modern HTTP client for Python that supports both synchronous and asynchronous requests. Let's compare the performance of synchronous vs asynchronous HTTP fetching using httpx.

First, install the httpx library using pip:

pip install httpx
Enter fullscreen mode Exit fullscreen mode

Now, let's create a simple example that fetches a URL using both synchronous and asynchronous requests:

import httpx
import asyncio
import time

def sync_fetch(url):
    response = httpx.get(url)
    return response.text

async def async_fetch(url):
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
        return response.text

async def main():
    url = "https://example.com"
    start_time = time.time()
    sync_response = sync_fetch(url)
    sync_time = time.time() - start_time
    print(f"Sync fetch time: {sync_time:.2f} seconds")

    start_time = time.time()
    async_response = await async_fetch(url)
    async_time = time.time() - start_time
    print(f"Async fetch time: {async_time:.2f} seconds")

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

In this example, we define two functions: sync_fetch and async_fetch. The sync_fetch function uses the synchronous httpx.get() method to fetch the URL, while the async_fetch function uses the asynchronous httpx.AsyncClient() to fetch the URL.

We then measure the time it takes to fetch the URL using both synchronous and asynchronous requests. The results will show that the asynchronous request is significantly faster than the synchronous request.

Benchmarks

To get a better understanding of the performance difference between synchronous and asynchronous requests, let's create a benchmark that fetches multiple URLs concurrently using both synchronous and asynchronous requests.

import httpx
import asyncio
import time

def sync_fetch(urls):
    responses = []
    for url in urls:
        response = httpx.get(url)
        responses.append(response.text)
    return responses

async def async_fetch(urls):
    async with httpx.AsyncClient() as client:
        tasks = [client.get(url) for url in urls]
        responses = await asyncio.gather(*tasks)
        return [response.text for response in responses]

async def main():
    urls = ["https://example.com"] * 10
    start_time = time.time()
    sync_responses = sync_fetch(urls)
    sync_time = time.time() - start_time
    print(f"Sync fetch time: {sync_time:.2f} seconds")

    start_time = time.time()
    async_responses = await async_fetch(urls)
    async_time = time.time() - start_time
    print(f"Async fetch time: {async_time:.2f} seconds")

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

In this benchmark, we fetch 10 URLs concurrently using both synchronous and asynchronous requests. The results will show that the asynchronous requests are significantly faster than the synchronous requests.

Conclusion

In conclusion, asynchronous programming is a powerful tool in Python that allows your code to perform multiple tasks concurrently, improving the overall performance and responsiveness of your application. The asyncio library provides a simple and efficient way to write asynchronous code, and the httpx library provides a modern HTTP client that supports both synchronous and asynchronous requests.

By using asynchronous requests, you can significantly improve the performance of your application, especially when dealing with I/O-bound tasks such as HTTP requests. The benchmarks shown in this tutorial demonstrate the performance difference between synchronous and asynchronous requests, and they provide a clear example of the benefits of using asynchronous programming in Python.


📧 Found this helpful? Follow me on Dev.to for weekly tutorials on Python automation, developer tools, and making money as a programmer!


喜欢这篇文章?关注获取更多Python自动化内容!


🔗 Recommended Resources

Note: Some links are affiliate links. Using them supports this blog at no extra cost to you.


If you found this useful, you might like Python Automation Scripts Pack (10 Ready-to-Use Tools) — a practical resource that takes things a step further. At $14.99 it's a solid investment for your toolkit.

Top comments (0)