使用matplotlib FuncAnimation时报'tuple object is not callable'如何解决
错误根因
FuncAnimation的func和init_func参数要求传入可调用的函数对象,你在代码中直接执行了animate()和init()函数,这两个函数的返回值是包含绘图对象的元组,因此运行时抛出TypeError: 'tuple' object is not callable错误。
修复方案
1. 修正FuncAnimation实例化参数
不要直接执行animate和init函数,额外参数通过官方提供的传参入口传入,修改后代码如下:
anim = animation.FuncAnimation( fig, animate, # 仅传入函数名,不要加括号执行 fargs=(400 * (shardN - 1),), # 按顺序传入animate除帧序号i之外的参数 init_func=lambda: init(pplotted=400 * (shardN - 1), linesn=4, data=data), # 用lambda包装init函数传参,兼容所有matplotlib版本 frames=range(400 * (shardN - 1), 400 * shardN), # 帧序号匹配当前分段的实际下标范围 interval=20, blit=True, cache_frame_data=False, )
如果你的matplotlib版本≥3.3,也可以用官方init_fargs参数代替lambda写法:
init_func=init, init_fargs=(400 * (shardN - 1), 4, data),
2. 优化其他潜在问题
- 去掉循环内的
plt.show()调用,会阻塞动画保存流程。 - 现有更新函数中每次调用
ax.text都会新增文本对象,不会自动覆盖旧内容,会导致内存占用随帧数升高越来越卡,建议提前创建text对象,每次更新仅修改内容:
先在子图初始化后新增文本对象定义:
再把animate函数中原text创建代码替换为:text1 = ax1.text(max(Time) / 10, 1500, "", fontsize=8) text2 = ax2.text(max(Time) / 10, max(RotSpeed) / 13, "", fontsize=8) text3 = ax3.text(max(Time) / 10, max(RotThrust) / 10, "", fontsize=8) text4 = ax4.text(max(Time) / 10, 1, "", fontsize=8)text1.set_text("GenPwr (kW)=" + str(GenPwr[i])) text2.set_text("RotSpeed (rpm)=" + str(RotSpeed[i])) text3.set_text("RotThrust (kW)=" + str(RotThrust[i])) text4.set_text("WindVel (m/s)=" + str(round(WindVel[i], 2))) - 所有分段生成完成后,可直接用ffmpeg的concat模式无损拼接,先创建
filelist.txt按行写入所有分片路径,格式为file 'animation_shard_序号.mp4',再执行命令:ffmpeg -f concat -safe 0 -i filelist.txt -c copy full_animation.mp4
内容的提问来源于stack exchange,提问作者ghylander
相关产品推荐
相关产品推荐

