Python装饰器中如何获取被包装任意函数的父模块名称
获取被装饰函数所属模块名的实现方案
Python 函数对象原生自带__module__属性,不需要额外实现parent_module这类自定义属性,直接读取即可拿到函数定义所在的模块名。
核心用法
函数定义完成后,Python 会自动给函数对象绑定__module__属性,属性值为字符串类型,存储函数定义所在模块的全限定名:
- 定义在根目录
my_lib.py的函数,func.__module__值为my_lib - 定义在包路径
pkg/utils.py的函数,func.__module__值为pkg.utils - 内置函数(比如
print)的__module__值为builtins - 类中定义的方法,
__module__值为类定义所在的模块名,完全覆盖日志、信息上报的使用场景
修正后的装饰器代码
你原来的代码存在两个问题:一是错误使用了不存在的parent_module属性,二是return func(*args, **kwargs)缩进错误,写到了wrapper函数外部,会导致装饰器加载时就直接执行被装饰函数,而非调用时触发逻辑。修正后可直接运行的代码如下:
from functools import wraps def my_decorator(func): @wraps(func) def wrapper(*args, **kwargs): # 直接读取原生__module__属性获取所属模块名 print(f"Wrapping function {func.__name__} from module {func.__module__}") return func(*args, **kwargs) return wrapper
补充说明
- 不推荐优先使用
inspect.getmodule(func)方案:该方法会在运行时遍历sys.modules匹配所属模块,性能比直接读__module__差,且当函数所属模块未被加载到sys.modules时会返回None,稳定性不足 - 如果确实需要拿到模块对象而非模块名字符串,可以通过
sys.modules[func.__module__]获取,但要注意捕获KeyError异常,兼容极端场景下模块未加载的情况 - 动态生成的函数、lambda表达式的
__module__属性同样会自动绑定为定义位置所属模块,不需要额外处理
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

