Solving Python asyncio error: object dict can’t be used in ‘await’ expression

Updated: February 12, 2024 By: Guest Contributor Post a comment

The Problem

When working with asynchronous programming in Python, particularly with the asyncio module, you may encounter the error message object dict can’t be used in ‘await’ expression. This error typically arises when you mistakenly attempt to await on a dictionary object, which is not a coroutine or an awaitable object. Understanding the nature of async programming and the awaitable protocol in Python is crucial for resolving this error. In this guide, we will explore the reasons behind this error and provide practical solutions to fix it.

Solutions to Fix the Error

Solution 1: Ensure You’re Awaiting a Coroutine

The most common reason for this error is attempting to await an object that is not awaitable (e.g., a dictionary). Ensure the object being awaited is a coroutine or another awaitable object.

  • Step 1: Identify the line of code causing the error. It generally involves the await keyword.
  • Step 2: Verify that the object being awaited is a coroutine function or an awaitable object. If it’s a dictionary, you’re likely trying to await the result of a function that returns a dictionary instead of awaiting the function itself.
  • Step 3: Modify your code to await the correct object.

Example:

async def get_data():
    # Simulate an asynchronous operation that returns a dictionary
    await asyncio.sleep(1)
    return {'key': 'value'}

async def main():
    result = await get_data()
    print(result)

asyncio.run(main())

Notes: This approach is straightforward and addresses the root cause of the error. However, it requires understanding of async programming and identifying which objects are awaitable.

Solution 2: Convert the Dictionary to an Awaitable Object

If your logic genuinely requires awaiting a dictionary (though unconventional), you can wrap the dictionary in an object that implements the await protocol.

  • Step 1: Create a custom class that wraps the dictionary and implements the __await__ method.
  • Step 2: Within the __await__ method, yield a coroutine or another awaitable object that logically should complete before allowing access to the dictionary’s data.
  • Step 3: Use instances of this class wherever you were encountering the error.

Example:

class AwaitableDict:
    def __init__(self, dictionary):
        self.dictionary = dictionary

    def __await__(self):
        # Implement the await logic here
        # For demonstration: simply await asyncio.sleep()
        yield from asyncio.sleep(1).__await__()
        return self.dictionary

async def main():
    d = AwaitableDict({'key': 'value'})
    result = await d
    print(result)

asyncio.run(main())

Notes: This technique is more a workaround than a solution and might not be suitable for all situations. It introduces additional complexity and could make the code harder to read and maintain.