iscoroutinefunction vs. coroutines
Hi, Is this pattern def foo(): return bar() async def bar(): await <whatever> async def async_main(): await foo() considered to be valid? The reason I'm asking is that some code out there likes to accept a might-be-a-coroutine-function argument, using def run_callback(fn): if iscoroutinefunction(fn): res = await fn() else: res = fn() instead of def run_callback(fn): res = fn() if iscoroutine(res): res = await res() The former obviously breaks when somebody combines these idioms and calls run_callback(foo) but I can't help but wonder whether the latter use might be deprecated, or even warned about, in the future and/or with non-CPython implementations. -- -- Matthias Urlichs
On Thu, Mar 9, 2017 at 3:04 AM, Matthias Urlichs
Is this pattern
def foo(): return bar() async def bar(): await <whatever>
async def async_main(): await foo()
considered to be valid?
Yes, it is valid.
The reason I'm asking is that some code out there likes to accept a might-be-a-coroutine-function argument, using
def run_callback(fn): if iscoroutinefunction(fn): res = await fn() else: res = fn()
instead of
def run_callback(fn): res = fn() if iscoroutine(res): res = await res()
The former obviously breaks when somebody combines these idioms and calls
run_callback(foo)
but I can't help but wonder whether the latter use might be deprecated, or even warned about, in the future and/or with non-CPython implementations.
In general I would recommend against patterns that support either awaitables or non-awaitables. The recommended solution is for run_callback() to require an awaitable, and if you have a function that just returns the value, you should wrap it in an async def that doesn't use await. The difference between the two versions of run_callback() is merely the difference you pointed out -- iscoroutinefunction(f) is not entirely equivalent to iscoroutine(f()). If you're thinking in terms of static types (e.g. PEP 484 and mypy), in the latter version the type of `res` is problematic (it's Union[Awaitable[T], T]), but there's an easy way to rewrite it to avoid that, while still calling iscoroutine(). If there's something else you worry about with the latter please clarify. But in general I would stay far away from this kind of "do what I mean" API -- they are hard to reason about and difficult to debug. -- --Guido van Rossum (python.org/~guido)
participants (2)
-
Guido van Rossum
-
Matthias Urlichs