能,inspect.iscoroutinefunction仅准确识别标准async def定义的函数,不识别@asyncio.coroutine装饰的函数、装饰器包装后的协程、partial对象或lambda;检测类方法需传未绑定函数,且不检查类型注解。

inspect.iscoroutinefunction 能准确识别 async def 定义的函数吗
能,但仅限于标准协程函数(即用 async def 定义的函数)。它对 asyncio.coroutine 装饰器标记的生成器函数(已弃用)、普通生成器、返回 awaitable 的同步函数,或被装饰器包装后的协程函数,都会返回 False。
常见误判场景:
- 给
async def foo()加了@wraps或自定义装饰器后,inspect.iscoroutinefunction(foo)可能失效——因为装饰器通常返回新函数对象,丢失原始协程标记 -
lambda无法写成协程,所以inspect.iscoroutinefunction(lambda: ...)永远为False - 类方法或静态方法中用了
async def,检测时需传入未绑定的函数(如MyClass.mymethod),而非实例方法对象(如obj.mymethod)
为什么 inspect.iscoroutinefunction 对 asyncio.coroutine 装饰的函数返回 False
因为 asyncio.coroutine 是 Python 3.4 的临时方案,它只是给生成器函数打上 ._is_coroutine = True 属性,并不改变函数类型。而 inspect.iscoroutinefunction 内部只检查 CO_COROUTINE 标志位(由 async def 编译时设置),不读取运行时属性。
验证方式:
import asyncio import inspect <p>@asyncio.coroutine def legacy(): yield from asyncio.sleep(0.1)</p><p>print(inspect.iscoroutinefunction(legacy)) # False print(hasattr(legacy, '_is_coroutine')) # True </p>
结论:不要混用旧装饰器和现代检测函数;Python 3.7+ 应彻底弃用 @asyncio.coroutine。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
检测协程函数时容易忽略的边界情况
实际工程中常漏掉这些点:
- 模块动态导入后,函数可能被重赋值(如
myfunc = getattr(module, 'foo')),需确保检测的是原始函数对象,而非中间变量 - 使用
functools.partial包装协程函数后,结果是partial对象,inspect.iscoroutinefunction必然返回False - PyPy 和某些 C 扩展模块中,协程函数可能因实现差异不满足 CPython 的字节码检查逻辑(极少见,但 CI 中偶有报错)
- 类型提示里的
Coroutine或Awaitable注解不影响运行时判断,inspect不看注解
比 iscoroutinefunction 更实用的替代方案有哪些
单靠 inspect.iscoroutinefunction 往往不够,尤其在框架层需要统一调度时:
- 想确认“调用后是否可 await”,应改用
inspect.isawaitable(obj())(先调用再检测返回值) - 要兼容装饰器包装,可用
inspect.unwrap(func)后再检测:inspect.iscoroutinefunction(inspect.unwrap(func)) - 若需区分协程函数、异步生成器函数、普通函数,组合使用:
inspect.iscoroutinefunction、inspect.isasyncgenfunction、inspect.isfunction - 注意:
inspect.iscoroutine检测的是协程对象(即调用协程函数后的结果),不是函数本身,别混淆两者
真正难的不是判断函数是不是协程,而是判断你手上的那个对象——它到底是函数、方法、partial、代理、还是被多层装饰器裹得严严实实的黑盒。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










