升级Matplotlib后调用figurecanvasTkagg.draw()触发ZeroDivisionError
解决Matplotlib升级后ZeroDivisionError(height_ratios除零)问题
问题背景
代码正常运行多年,升级Matplotlib后调用figurecanvasTkagg.draw()时触发ZeroDivisionError,错误源于matplotlib/_layoutgrid.py的grid_constraints方法中执行h0 = h / self.height_ratios[0]时的除零操作。即使创建Figure时设置了layout='constrained',问题仍存在。
复现代码(简化版)
self.fig = Figure(figsize=(5, 4), dpi=100, layout='constrained') self.__plot = self.fig.add_subplot(111) self.__plot.set_xlim(datetime.strptime('01/05/' + year + '00:00:00', '%d/%m/%Y %H:%M:%S'), datetime.strptime('01/12/' + year + ' 00:00:00', '%d/%m/%Y %H:%M:%S')) self.__plot.invert_yaxis() cf = self.__plot.contourf(df_datetime, -depths, df.values.T, 256, extend='both', cmap='RdYlBu_r', levels=levels2) self.__cb = plt.colorbar(cf, ax=self.__plot, label='Temperature (ºC)', ticks=levels) self.__cbexists = True self.__plot.set(ylabel='Depth (m)', title=historical.split('_')[4] + ' year ' + year) locator = mdates.MonthLocator() self.__plot.xaxis.set_major_locator(locator) fmt = mdates.DateFormatter('%b') self.__plot.xaxis.set_major_formatter(fmt) # Sets the x axis on the top self.__plot.xaxis.tick_top() # Sets the ticks only for the whole depths, the ones from the file tick_depths = [-i for i in depths if i.is_integer()] self.__plot.set_yticks(tick_depths) self.canvas.draw()
可行解决方案
1. 手动控制颜色条布局,避免自动计算异常
使用mpl_toolkits.axes_grid1的make_axes_locatable创建独立的颜色条轴,绕开Constrained Layout的自动比例计算:
from mpl_toolkits.axes_grid1 import make_axes_locatable # 分割子图轴,为颜色条预留空间 divider = make_axes_locatable(self.__plot) cax = divider.append_axes("right", size="5%", pad=0.1) # 使用预留的轴创建颜色条 self.__cb = self.fig.colorbar(cf, cax=cax, label='Temperature (ºC)', ticks=levels)
2. 切换布局模式为tight
替换constrained布局为tight,或手动调用tight_layout:
# 创建Figure时指定tight布局 self.fig = Figure(figsize=(5, 4), dpi=100, layout='tight') # 或者在draw前手动触发tight布局 # self.fig.tight_layout() self.canvas.draw()
3. 显式设置子图高度比例
若坚持使用Constrained Layout,手动设置子图网格的高度比例,确保第一个比例不为零:
# 显式设置单张子图的高度比例为[1] self.__plot.get_gridspec().set_height_ratios([1])
4. 检查并修正数据范围异常
确认depths数据无异常值,确保y轴范围合理:
# 检查深度数据 print("Depths data:", depths) # 强制设置y轴范围,避免自动计算出极端值 self.__plot.set_ylim(min(-depths), max(-depths))
内容的提问来源于stack exchange,提问作者Marc JB
相关产品推荐
相关产品推荐

