How to check if a callable object is async using inspect module? - python

Viewed 70

I need an efficient and pythonic way to check if a callable object is async or not inspect.iscoroutinefunction fails to identify that, I've tried this:

import inspect
        
async def test_func() -> None:
    pass
        
class TestClass:
    async def __call__(self) -> None:
        pass

test_obj = TestClass()

when testing:

inspect.iscoroutinefunction(test_func)
>>> True

inspect.iscoroutinefunction(test_obj)
>>> False

and when testing:

inspect.iscoroutinefunction(test_func.__call__)
>>> False

inspect.iscoroutinefunction(test_obj.__call__)
>>> True

I can make a helper function like:

def is_async(func: Callable) -> bool:
    try:
       return any(map(inspect.iscoroutinefunction, (func, func.__call__)))
    except AttributeError:
        return False

But I feel that there's something simpler...

1 Answers

This is from starlette:

import asyncio
import functools
import typing


def is_async_callable(obj: typing.Any) -> bool:
    while isinstance(obj, functools.partial):
        obj = obj.func

    return asyncio.iscoroutinefunction(obj) or (
        callable(obj) and asyncio.iscoroutinefunction(obj.__call__)
    )
Related