You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

全局变量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()

关键修改点说明

  1. 作用域修正:用nonlocal curr_pos替代global,让嵌套的key_event函数能正确访问并修改外层manual()函数中的curr_pos变量,彻底解决NameError。
  2. 曲线可见性控制:预先绘制所有73条曲线,默认隐藏,切换时只修改曲线的visible属性——完全保留你的坐标轴设置,也不会因为重复绘制导致卡顿。
  3. 代码优化:一次性清理数据、用os.path.join处理路径、用draw_idle()高效重绘,让代码更简洁可靠。
  4. 循环切换逻辑:用% len(curve_list)确保左右键可以循环切换(比如从最后一条按右键回到第一条)。

内容的提问来源于stack exchange,提问作者trashdragon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 13:52:26