Issue
I am puzzled by the following behavior in Python 3.6+:
>>> def f1(): pass
>>> def f2(): yield
>>> async def f3(): pass
>>> async def f4(): yield
>>> inspect.isfunction(f1)
True
>>> inspect.isfunction(f2)
True
>>> inspect.iscoroutinefunction(f3)
True
>>> inspect.iscoroutinefunction(f4)
False
Both synchronous functions and generator functions are considered "functions" by inspect but asynchronous generator functions are not considered "coroutine functions". This seems contrary to the documentation
inspect.iscoroutinefunction(object)
Return true if the object is a coroutine function (a function defined with an async def syntax).
Is there any better way to detect if a function was defined with async
, including generator functions, than checking both iscoroutinefunction
and isasyncgenfunction
?
This may be due to the fact that asynchronous generators only appeared in 3.6 but is still puzzling.
Solution
Asynchronous generators are not themselves coroutines, and cannot be await
ed:
>>> loop.run_until_complete(f4())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/haugh/.pyenv/versions/3.6.6/lib/python3.6/asyncio/base_events.py", line 447, in run_until_complete
future = tasks.ensure_future(future, loop=self)
File "/home/haugh/.pyenv/versions/3.6.6/lib/python3.6/asyncio/tasks.py", line 526, in ensure_future
raise TypeError('An asyncio.Future, a coroutine or an awaitable is '
TypeError: An asyncio.Future, a coroutine or an awaitable is required
I think you have already identified the best way of checking if async
was used to define the function:
def async_used(func):
return inspect.iscoroutinefunction(func) or inspect.isasyncgenfunction(func)
Answered By - Patrick Haugh
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.