全局变量curr_pos引发NameError及ax.cla()性能卡顿问题(Python+Matplotlib)
解决你的Matplotlib按键切换绘图问题
问题根源拆解
1. NameError的核心原因
你在key_event函数里用了global curr_pos,但curr_pos其实是manual()函数的局部变量,并非全局变量——Python找不到这个全局变量,自然会抛出NameError。之前你尝试把curr_pos放在key_event内部,又会导致每次按键触发时变量被重置,所以只能切换一次就卡住。
2. 不用ax.cla()的替代方案
ax.cla()会清除整个坐标轴,不仅会重置你精心设置的刻度、范围,还会因为重复绘制曲线导致卡顿。更优的思路是:预先绘制所有曲线,通过控制曲线的可见性来切换,这样既能保留坐标轴设置,又不会产生性能问题。
修正后的完整代码
def manual(): import os import pandas as pd import matplotlib.pyplot as plt from matplotlib.ticker import MultipleLocator date = '20200121' QD = 'QD053' # 用os.path.join拼接路径,更规范且跨平台 path = os.path.join(all_DATA_DIR, date, QD, 'CSVs') for filename in os.listdir(path): if not filename.startswith('Pol'): continue df = pd.read_csv(os.path.join(path, filename), header=0, engine='python', index_col=None, sep=',') # 一次性清理数据,避免重复调用drop df_clean = df.drop(index=[0, 1, 2]) x_data = df_clean['Wavelength'] # 初始化绘图组件,只做一次坐标轴设置 fig = plt.figure() ax = fig.add_subplot(111) ax.yaxis.set_major_locator(MultipleLocator(5000)) ax.xaxis.set_major_locator(MultipleLocator(50)) ax.grid(which='minor', linestyle=':', linewidth=0.3, color='grey') ax.grid(which='major', linestyle='-', linewidth=0.5, color='grey') ax.set_ylim([-1000, 60000]) plt.xticks(rotation=70) # 预先绘制所有曲线,存储Line2D对象用于控制可见性 curve_list = [] for spec_num in range(1, 74): y_data = df_clean[f'Spec{spec_num}'] line, = ax.plot(x_data, y_data, alpha=0.6) line.set_visible(False) # 默认隐藏所有曲线 curve_list.append(line) # 初始显示第一条曲线 curr_pos = 0 curve_list[curr_pos].set_visible(True) def key_event(e): nonlocal curr_pos # 声明访问外层函数的curr_pos变量,替代错误的global prev_pos = curr_pos # 记录上一次的位置,用于隐藏旧曲线 # 更新当前位置,用取模确保循环切换 if e.key == "right": curr_pos = (curr_pos + 1) % len(curve_list) elif e.key == "left": curr_pos = (curr_pos - 1) % len(curve_list) else: return # 切换曲线可见性 curve_list[prev_pos].set_visible(False) curve_list[curr_pos].set_visible(True) fig.canvas.draw_idle() # 高效重绘,比draw()性能更好 fig.canvas.mpl_connect('key_press_event', key_event) plt.show() if __name__ == '__main__': manual()
关键修改点说明
- 作用域修正:用
nonlocal curr_pos替代global,让嵌套的key_event函数能正确访问并修改外层manual()函数中的curr_pos变量,彻底解决NameError。 - 曲线可见性控制:预先绘制所有73条曲线,默认隐藏,切换时只修改曲线的
visible属性——完全保留你的坐标轴设置,也不会因为重复绘制导致卡顿。 - 代码优化:一次性清理数据、用
os.path.join处理路径、用draw_idle()高效重绘,让代码更简洁可靠。 - 循环切换逻辑:用
% len(curve_list)确保左右键可以循环切换(比如从最后一条按右键回到第一条)。
内容的提问来源于stack exchange,提问作者trashdragon
相关产品推荐
相关产品推荐

