Python asyncio:生成器协程可通过哪个类型使isinstance返回True?
判断生成器协程是否为可等待对象的正确方式
这确实是个容易踩坑的点——虽然PEP-0492明确把生成器协程(被@asyncio.coroutine装饰的生成器)归为可等待对象,但typing.Awaitable和collections.abc.Awaitable的isinstance检查确实识别不了它们,原因是这些生成器对象并没有实现__await__方法(原生协程对象才有),而Awaitable抽象基类的实例判断逻辑就是检查对象是否有__await__属性。
最推荐的解决方案:使用inspect.isawaitable()
Python标准库的inspect模块提供了isawaitable()函数,它专门用来判断一个对象是否可以被await关键字处理,完美覆盖*生成器协程、原生协程、asyncio.Task、asyncio.Future*等所有可等待对象类型。
示例代码:
import asyncio import inspect import typing @asyncio.coroutine def generator_coroutine(): yield from asyncio.sleep(1) async def native_coroutine(): await asyncio.sleep(1) # 测试生成器协程对象 gen_obj = generator_coroutine() print(inspect.isawaitable(gen_obj)) # 输出: True print(isinstance(gen_obj, typing.Awaitable)) # 输出: False # 测试原生协程对象 native_obj = native_coroutine() print(inspect.isawaitable(native_obj)) # 输出: True print(isinstance(native_obj, typing.Awaitable)) # 输出: True
如果一定要用isinstance判断
如果你场景里必须用isinstance,可以结合inspect.isgenerator()和asyncio.coroutines.is_coroutine()(这个是asyncio内部的辅助函数,Python 3.6及以上版本可用),来判断生成器协程:
import asyncio import inspect import typing def is_awaitable_obj(obj): # 先检查是否是原生协程或实现__await__的对象 if isinstance(obj, typing.Awaitable): return True # 再检查是否是生成器协程 return inspect.isgenerator(obj) and asyncio.coroutines.is_coroutine(obj)
不过这里还是更推荐直接用inspect.isawaitable(),它是官方专门设计来解决这类判断问题的,简洁且不易出错。
内容的提问来源于stack exchange,提问作者nodakai
相关产品推荐
相关产品推荐

