Python async Keyword

The async keyword in Python is used to define asynchronous functions, also known as coroutines. These functions allow Python to handle tasks concurrently, improving performance in I/O-bound operations like web requests, database queries, and file handling.

Syntax

</>
Copy
async def function_name():
    # Async function body
    pass

How async Works

When a function is defined using async, it returns a coroutine object instead of executing immediately. To execute the coroutine, it must be awaited using the await keyword inside another async function or run inside an event loop.


Examples

1. Defining and Running an Async Function

In this example, we define an asynchronous function and run it using Python’s event loop.

When we define a function with async def, it doesn’t execute immediately. Instead, calling the function returns a coroutine object. We then use asyncio.run() to run this coroutine inside an event loop.

</>
Copy
import asyncio

# Define an async function
async def greet():
    print("Hello, async world!")

# Run the async function
asyncio.run(greet())

Output:

Hello, async world!

Here, asyncio.run(greet()) starts an event loop and runs the coroutine greet(), printing the message to the console.

2. Using await Inside an Async Function

We use await inside an async function to pause execution until an awaited function completes. This allows other tasks to run in the meantime, improving efficiency.

</>
Copy
import asyncio

# Define an async function with await
async def delayed_message():
    print("Waiting for 2 seconds...")
    await asyncio.sleep(2)  # Simulates an async delay
    print("Done waiting!")

# Run the async function
asyncio.run(delayed_message())

Output:

Waiting for 2 seconds...
Done waiting!

Here, await asyncio.sleep(2) pauses the function for 2 seconds without blocking other tasks. Once the delay is over, execution resumes and prints “Done waiting!”.

3. Running Multiple Async Tasks Concurrently

Using asyncio.gather(), we can run multiple async functions at the same time instead of waiting for each one to finish before starting the next.

</>
Copy
import asyncio

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

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

async def main():
    await asyncio.gather(task1(), task2())  # Run both tasks concurrently

asyncio.run(main())

Output:

Task 1 complete
Task 2 complete

Instead of waiting for task1() to finish before starting task2(), both tasks run concurrently, improving efficiency.

4. Handling Errors in Async Functions

Errors in async functions can be caught using try-except. This helps prevent the entire event loop from crashing when an error occurs.

</>
Copy
import asyncio

async def risky_function():
    try:
        print("Starting risky task...")
        await asyncio.sleep(1)
        raise ValueError("Something went wrong!")
    except ValueError as e:
        print("Caught an error:", e)

asyncio.run(risky_function())

Output:

Starting risky task...
Caught an error: Something went wrong!

Here, if an error occurs inside risky_function(), it is caught and handled gracefully instead of stopping the entire program.