2201_75335496 2024-06-23 21:35 采纳率: 76.5%
浏览 3
已结题

python plt.subplots创建画布时过大导致报错怎么办?

def closewin():pass
    def draw():
        load_start_time = time.time()
        with open("./StartUp.log","r",encoding = "utf-8") as f:
            text = json.loads(f.read())
        pb["value"] = 10
        win.update()
        namelist = []
        valuelist = []
        for i in range(len(text)):
            valuelist.append([])
            for k,v in text[i].items():
                if not k in namelist:
                    namelist.append(k)
                valuelist[i].append(v)
        #print(namelist)
        #print(valuelist)
        pb["value"] = 20
        win.update()
        # 生成一个包含随机数据的表格
        plt.rcParams['font.family'] = 'SimHei'
        d = pd.DataFrame(valuelist, columns=namelist).round(2)
        pb["value"] = 30
        win.update()
        fig, ax = plt.subplots(figsize=(len(namelist) * 4.2,len(valuelist) + 2))
        pb["value"] = 35
        win.update()
        # 基于pandas表格数据创建和展示图形表格
        column_definitions = []
        for i in namelist:
            column_definitions.append(ColumnDefinition(name = i,border = "l"))
            column_definitions.append(ColumnDefinition(name = i,border = "both"))
        pb["value"] = 40
        win.update()
        tab = Table(d,column_definitions = column_definitions)
        pb["value"] = 50
        win.update()
        # 保存图片
        plt.savefig("table.jpg", dpi=300,bbox_inches='tight')
        pb["value"] = 90
        win.update()
        os.startfile("table.jpg")
        #plt.show()
        plt.close()
        pb["value"] = 100
        pl.config(text = "可以关闭!")
        win.update()
        win.protocol("WM_DELETE_WINDOW",partial(win.destroy))
        load_end_time = time.time()
        print("数据加载时间:",load_end_time - load_start_time)

在数据过多时,python plt.subplots创建画布时过大,导致报错

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 749, in callit
    func(*args)
  File "C:\Users\Administrator\Desktop\PYExe\2024项目\系统工具\开机启动\StartUp_Log_Viewer.py", line 96, in draw
    fig, ax = plt.subplots(figsize=(len(namelist) * 4.2,len(valuelist) + 2))
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\pyplot.py", line 1453, in subplots
    fig = figure(**fig_kw)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\pyplot.py", line 809, in figure
    FigureClass=FigureClass, **kwargs)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\pyplot.py", line 325, in new_figure_manager
    return _get_backend_mod().new_figure_manager(*args, **kwargs)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\backend_bases.py", line 3494, in new_figure_manager
    return cls.new_figure_manager_given_figure(num, fig)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\backends\_backend_tk.py", line 965, in new_figure_manager_given_figure
    canvas = cls.FigureCanvas(figure, master=window)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\_api\deprecation.py", line 389, in wrapper
    return func(*inner_args, **inner_kwargs)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\backends\_backend_tk.py", line 176, in __init__
    master=self._tkcanvas, width=w, height=h)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 3545, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 3501, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: not enough free memory for image buffer

怎么修改?或者让其不需要展示到plt中就导出?

  • 写回答

2条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-06-23 21:35
    关注

    引自免费微信小程序:皆我百晓生

    要解决这个问题,我们可以尝试几个步骤来优化你的代码。首先,检查plt.subplots()函数是否正确地设置了绘图大小。其次,确保所有图像都是独立绘制的,并且不是在同一个子图中绘制。

    下面是针对你的问题的一些可能的解决方案:

    1. 检查绘图大小设置

    如果你正在调用plt.subplots()并设置了figsize参数,但仍然遇到内存不足的问题,可能是由于plt.subplots()默认设置的绘图尺寸过大导致。你可以尝试将figsize调整为更小的值,例如figsize=(10, 5)

    import matplotlib.pyplot as plt
    from matplotlib import cm
    from mpl_toolkits.axes_grid1 import host_subplot
    import numpy as np
    
    # 创建一些示例数据
    x = np.linspace(-np.pi, np.pi, 100)
    y = np.sin(x)
    
    # 创建一个包含随机数据的表格
    data = {'x': x, 'y': y}
    
    # 创建一个包含随机数据的表格
    df = pd.DataFrame(data, columns=['x', 'y'])
    
    # 将数据转换为numpy数组
    df = df.to_numpy()
    
    # 绘制图表
    fig, axs = plt.subplots(2, 2, figsize=(10, 5))
    
    for ax in axs.flat:
        ax.imshow(df, cmap=cm.coolwarm, origin="lower")
    
    axs[0][0].set_title('Plot 1')
    axs[0][1].set_title('Plot 2')
    axs[1][0].set_title('Plot 3')
    axs[1][1].set_title('Plot 4')
    
    # 显示图表
    plt.tight_layout()
    plt.show()
    

    在这个例子中,我们创建了一个包含两个子图的布局。每个子图都包含了来自pd.DataFrame的数据,然后使用imshow()函数绘制这些数据。这样可以有效地减少绘图资源占用。

    2. 独立绘制图像

    为了进一步提高性能,你可以考虑使用subplots_adjust方法来调整子图之间的间距,以便在同一子图上绘制多个图像。此外,你可以尝试一次性加载所有数据,而不是在每次循环中重新计算数据。

    import matplotlib.pyplot as plt
    from matplotlib import cm
    from mpl_toolkits.axes_grid1 import host_subplot
    import numpy as np
    
    # 创建一些示例数据
    x = np.linspace(-np.pi, np.pi, 100)
    y = np.sin(x)
    
    # 创建一个包含随机数据的表格
    data = {'x': x, 'y': y}
    
    # 创建一个包含随机数据的表格
    df = pd.DataFrame(data, columns=['x', 'y'])
    
    # 将数据转换为numpy数组
    df = df.to_numpy()
    
    # 绘制图表
    fig, axs = plt.subplots(2, 2, figsize=(10, 5), subplot_kw=dict(polar=True))
    
    for ax in axs.flat:
        ax.plot(df[:, 0], df[:, 1])
    
    axs[0][0].set_title('Plot 1')
    axs[0][1].set_title('Plot 2')
    axs[1][0].set_title('Plot 3')
    axs[1][1].set_title('Plot 4')
    
    # 显示图表
    plt.tight_layout()
    plt.show()
    

    在这个例子中,我们将子图类型设为polar,以便在一个子图中同时绘制多个坐标轴。通过这种方式,我们可以避免在每个子图中绘制相同的图像,从而节省内存。

    3. 导出图像

    如果你想在不显示图像的情况下导出图表,可以使用savefig函数,它会自动处理保存过程中的任何内存限制问题。

    import matplotlib.pyplot as plt
    from matplotlib import cm
    from mpl_toolkits.axes_grid1 import host_subplot
    import numpy as np
    
    # 创建一些示例数据
    x = np.linspace(-np.pi, np.pi, 100)
    y = np.sin(x)
    
    # 创建一个包含随机数据的表格
    data = {'x': x, 'y': y}
    
    # 创建一个包含随机数据的表格
    df = pd.DataFrame(data, columns=['x', 'y'])
    
    # 将数据转换为numpy数组
    df = df.to_numpy()
    
    # 绘制图表
    fig, axs = plt.subplots(2, 2, figsize=(10, 5), subplot_kw=dict(polar=True))
    
    for ax in axs.flat:
        ax.plot(df[:, 0], df[:, 1])
        ax.set_ylim([-1.5, 1.5])
    
    axs[0][0].set_title('Plot 1')
    axs[0][1].set_title('Plot 2')
    axs[1][0].set_title('Plot 3')
    axs[1][1].set_title('Plot 4')
    
    # 显示图表
    plt.tight_layout()
    plt.savefig('output.png', dpi=300)
    plt.close()
    

    这个例子中,我们在每个子图上只绘制了部分数据,并且设置了ylim范围以防止超出存储空间。然后使用savefig函数保存图表,这样就不需要显式地打开文件,而是在运行结束后自动保存。

    希望这些建议能帮助你解决问题。如果你有任何疑问或需要更多帮助,请随时告诉我!

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月23日
  • 创建了问题 6月23日

悬赏问题

  • ¥20 wpf datagrid单元闪烁效果失灵
  • ¥15 券商软件上市公司信息获取问题
  • ¥100 ensp启动设备蓝屏,代码clock_watchdog_timeout
  • ¥15 Android studio AVD启动不了
  • ¥15 陆空双模式无人机怎么做
  • ¥15 想咨询点问题,与算法转换,负荷预测,数字孪生有关
  • ¥15 C#中的编译平台的区别影响
  • ¥15 软件供应链安全是跟可靠性有关还是跟安全性有关?
  • ¥15 电脑蓝屏logfilessrtsrttrail问题
  • ¥20 关于wordpress建站遇到的问题!(语言-php)(相关搜索:云服务器)