
在跨文件导入场景下,通过 inspect 模块在类的 __init__ 方法中动态捕获调用者函数名是可行的,关键在于使用 inspect.currentframe().f_back 获取上一级栈帧,并借助 inspect.getframeinfo() 提取函数名。
在跨文件导入场景下,通过 `inspect` 模块在类的 `__init__` 方法中动态捕获调用者函数名是可行的,关键在于使用 `inspect.currentframe().f_back` 获取上一级栈帧,并借助 `inspect.getframeinfo()` 提取函数名。
要在类实例化时自动记录实际调用该类的函数名(例如 func),必须将获取逻辑放在运行时——即 __init__ 方法内部,而非类定义体中。这是因为类变量(如 func_name = ...)在模块加载时即被求值,此时调用栈尚未形成,无法访问调用上下文。
以下是推荐实现(file2.py):
import inspect
class A:
def __init__(self):
# 获取上一级调用栈帧的信息
frame_info = inspect.getframeinfo(inspect.currentframe().f_back)
self.func_name = frame_info.function # 如 'func'
对应 file1.py 中的调用保持不变:
from file2 import A
def func(): # ← 此函数名将被成功捕获
a = A()
print(a.func_name) # 输出: 'func'
✅ 注意事项:
- ❌ 不要在类体中直接赋值
func_name = ...—— 那属于静态定义,无法访问调用栈; - ✅ 必须在
__init__(或实例方法)中动态获取,确保执行时栈帧有效; - ⚠️
inspect.currentframe()可能受优化影响(如python -O),生产环境建议添加异常兜底; - ? 跨包/子模块导入同样适用,只要调用发生在函数内(而非模块顶层);
? 扩展提示:若需更健壮的调用链分析(如跳过装饰器、日志封装等中间层),可结合 inspect.stack() 迭代过滤 frame_info.function != '<module>'</module> 并检查 frame_info.code_context,但对绝大多数场景,上述 f_back + getframeinfo 已足够精准可靠。










