Sling Academy
Home/Python/Python: Handling exceptions when using async/await

Python: Handling exceptions when using async/await

Last updated: July 12, 2023

This concise, straight-to-the-point article will walk you through some different ways to deal with exceptions when using async/await in Python

Using try/except blocks

You can use the standard try/except blocks to catch and handle exceptions that may occur in async functions or await expressions. The main points are:

  1. Place the asynchronous code that may raise an exception within a try block.
  2. In the except block, handle the specific exception(s) that you expect to occur.
  3. Optionally, use a general except block to handle any unexpected exceptions.
  4. Handle the exception appropriately, such as logging an error, retrying the operation, or raising a different exception.

Example:

import asyncio

# Define an async function
async def async_function():
    try:
        # Async code that may raise an exception
        await asyncio.sleep(1)
        result = await async_operation()
    except asyncio.TimeoutError:
        print("Timeout error occurred.")
    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")

# This async function will raise an exception
async def async_operation():
    await asyncio.sleep(2)
    raise ValueError("Something went wrong.")

# Main function
async def main():
    try:
        await async_function()
    except Exception as e: 
        print(f"Error in main function: {str(e)}")

# Run the main function
asyncio.run(main())

Output:

An unexpected error occurred: Something went wrong.

Some thoughts:

  • Pros: This approach is simple, familiar, and explicit. It allows fine-grained control over which exceptions to catch and how to handle them.
  • Cons: This approach may be verbose and repetitive if there are many async functions or await expressions that may raise exceptions. It may also obscure the main logic of the code with too many try/except blocks.

Using asyncio.gather()

This approach involves using asyncio.gather() to handle exceptions when using async/await in Python. It enables concurrent execution of multiple async tasks and provides a simpler way to collect their results and handle exceptions.

  1. Create a list of coroutines or futures representing the async tasks you want to execute.
  2. Use asyncio.gather() to concurrently execute the tasks.
  3. Await the result of asyncio.gather() to retrieve the results and handle exceptions, if any.

Code example:

import asyncio

async def async_task1():
    await asyncio.sleep(2)
    raise ValueError("Error in async_task1")

async def async_task2():
    await asyncio.sleep(3)
    return "Result from async_task2"

async def main():
    tasks = [async_task1(), async_task2()]
    try:
        results = await asyncio.gather(*tasks)
        print(f"Results: {results}")
    except ValueError as e:
        print(f"A value error occurred: {str(e)}")
    except Exception as e:
        print(f"Something went wrong: {str(e)}")

asyncio.run(main())

Output:

A value error occurred: Error in async_task1

Pros & cons:

  • Pros: Enables concurrent execution of multiple async tasks and simplifies exception handling by automatically raising the first exception encountered.
  • Cons: Only raises the first exception, potentially hiding subsequent exceptions.

That’s it. Happy coding & enjoy your day!

Next Article: Python asyncio.Semaphore class (with examples)

Previous Article: Python async/await and timeouts (with examples)

Series: Python Asynchronous Programming Tutorials

Python

You May Also Like

  • Python TypeError: write() argument must be str, not bytes
  • 4 ways to install Python modules on Windows without admin rights
  • Python TypeError: object of type ‘NoneType’ has no len()
  • Python: How to access command-line arguments (3 approaches)
  • Understanding ‘Never’ type in Python 3.11+ (5 examples)
  • Python: 3 Ways to Retrieve City/Country from IP Address
  • Using Type Aliases in Python: A Practical Guide (with Examples)
  • Python: Defining distinct types using NewType class
  • Using Optional Type in Python (explained with examples)
  • Python: How to Override Methods in Classes
  • Python: Define Generic Types for Lists of Nested Dictionaries
  • Python: Defining type for a list that can contain both numbers and strings
  • Using TypeGuard in Python (Python 3.10+)
  • Python: Using ‘NoReturn’ type with functions
  • Type Casting in Python: The Ultimate Guide (with Examples)
  • Python: Using type hints with class methods and properties
  • Python: Typing a function with default parameters
  • Python: Typing a function that can return multiple types
  • Python: Typing a function with *args and **kwargs