函数内提取pandas DataFrame名保存相关性图文件名异常问题
问题根因
你写的get_df_name通过遍历globals()匹配对象的逻辑天生不稳定,和变量名是否包含下划线没有关系:
globals()会返回全局作用域下所有变量,除了你自定义的DataFrame,还包括Python运行时自动生成的临时变量、导入的模块/函数;如果你是在IPython/Jupyter环境下运行,还会自动生成_、__、___三个临时变量,分别存放最近3次单元格执行的输出结果。- 你用
is做身份匹配时,如果这些下划线开头的临时变量恰好指向你传入的DataFrame(比如你之前单独运行过df_nodate没有做赋值,IPython就会自动把这个对象绑定到_类临时变量上),列表推导取第一个匹配项[0]时,就会先拿到这些短的下划线变量名,最终拼接出cor__.png这类错误文件名。 - 这个写法还有其他隐患:如果同一个DataFrame被赋值给多个全局变量,取到的名字完全由globals遍历顺序决定,结果随机;如果传入的DataFrame是函数内部生成的局部变量,还会直接触发索引越界报错。
修复方案
不要通过遍历全局作用域反查变量名,最稳妥的方案是调用时显式传入保存文件名,不想额外传参的话,可以通过解析调用栈的源码文本获取传入参数的原始变量名,稳定性远高于扫globals的方案:
import seaborn as sns import os import matplotlib.pyplot as plt import inspect def get_df_name(df): # 读取上一级调用栈的代码内容,提取第一个位置参数的原始文本 prev_frame = inspect.currentframe().f_back code_line = inspect.getframeinfo(prev_frame, context=1).code_context[0].strip() first_param = code_line[code_line.index("(")+1:].split(",")[0].strip() return first_param def cor(data, figsize): # 自动创建输出目录,避免路径不存在报错 os.makedirs("cor_plots", exist_ok=True) fig = plt.figure(figsize=figsize) corr = data.corr() ax = sns.heatmap( corr, vmin=-1, vmax=1, center=0, cmap=sns.diverging_palette(20, 220, n=200), square=True, annot=True ) ax.set_xticklabels( ax.get_xticklabels(), rotation=45, horizontalalignment='right' ) df_name = get_df_name(data) path = os.path.join("cor_plots", f"cor_{df_name}.png") # 增加tight布局避免标签截断,存完关闭图对象释放内存 fig.savefig(fname=path, bbox_inches="tight") plt.close(fig)
这个实现直接读取你写的cor(xxx, figsize=...)那行代码,提取第一个入参的原始文本作为变量名,不会被全局作用域的临时变量干扰。如果遇到传入的是表达式(比如cor(df_nodate.dropna(), (8,6))),提取到的会是表达式文本,这种场景可以给cor函数加个可选的save_name参数,特殊场景手动指定文件名即可。
内容的提问来源于stack exchange,提问作者miaa
相关产品推荐
相关产品推荐

