Declaring a function with async def
signals that it’s a coroutine, typically because it needs to use await
for
non-blocking operations (like I/O), or employs other asynchronous features like async for
or async with
.
If none of these asynchronous mechanisms are utilized within the function’s body, the async
declaration is superfluous.
Using async
unnecessarily can:
- Reduce Code Clarity: It misleads developers into thinking the function performs asynchronous operations when it doesn’t,
making the codebase harder to understand and reason about.
- Introduce Minor Overhead: Calling an
async def
function creates a coroutine object. While modern Python is
efficient, this still incurs more overhead than a direct synchronous function call if the asynchronicity isn’t actually leveraged. The function’s
body will execute synchronously until an await
(if any) is encountered. If there’s no await
or other async feature, it
essentially runs synchronously but wrapped as a coroutine.
- Complicate Usage: Callers must use
await
(or schedule it as a task) to execute the coroutine and get its result.
This is an unnecessary ceremony if the function itself isn’t truly asynchronous.