1. 问题根源:为什么你的字体缓存总出问题?
不知道你有没有遇到过这种情况:在Jupyter Notebook里折腾了半天,好不容易给matplotlib装了个新字体,满心欢喜地以为终于能告别宋体,结果一运行代码,图表上的中文要么是乱码,要么还是那个万年不变的默认字体。你照着网上教程,信心满满地敲下 font_manager._rebuild(),结果终端冷冷地抛给你一个 AttributeError: module 'matplotlib.font_manager' has no attribute '_rebuild'。那一刻,是不是感觉血压都上来了?
我刚开始用matplotlib做数据可视化的时候,这个问题真是让我头疼了好一阵子。后来我才搞明白,这其实是一个典型的“版本变迁”带来的坑。很多流传甚广的教程,包括一些几年前写的经典博客,它们基于的可能是matplotlib 2.x或者更早的版本。在那个时期,font_manager模块里确实有一个叫_rebuild()的内部方法,专门用来强制重建字体缓存。这个方法简单粗暴,对于解决字体更新后不生效的问题非常有效,所以被很多人记在了小本本上。
但是,软件是在不断迭代的。至少从matplotlib 3.4.2版本开始,开发团队可能出于代码结构优化或者API清理的考虑,移除了这个_rebuild()方法。你想想看,一个以下划线开头的方法,在Python的约定里通常意味着它是“私有”的、内部使用的,并不保证对外部用户的稳定性。所以,在新版本里找不到它,是完全合理的事情。如果你用的是3.5、3.6甚至更新的版本,那这个方法铁定是不存在了。盲目照搬老教程,自然就会踩进这个坑里。
那么,_rebuild()到底干了什么呢?它的核心目的其实就一个:清除旧的、可能已经过时或损坏的字体缓存文件,并触发matplotlib重新扫描系统字体目录,生成一份新的缓存。matplotlib为了提升启动和加载字体的速度,会把系统里可用的字体信息(比如字体路径、名称、样式等)预先扫描一遍,然后保存成几个缓存文件(通常是.json格式)。下次启动时,就直接读取这些缓存,而不用再全盘扫描。这本来是个提升效率的好设计,但当我们新增了字体,或者修改了字体配置时,这个缓存就成了“绊脚石”——因为它记录的还是老信息,新字体自然不会被识别。
所以,问题的本质就很清晰了:我们的目标不是去调用某个可能已经消失的魔法方法,而是要去完成“清除缓存并触发重建”这个动作本身。只要能达到这个目的,方法可以有很多种。_rebuild()只是其中一条路,此路不通,我们就换一条更直接、更底层、而且几乎在所有版本都通用的路来走。
2. 核心替代方案:手动清除缓存目录
既然_rebuild()这条路在新版本走不通了,我们就得自己动手,完成它原本要干的两件事:1. 找到并删除缓存文件;2. 让matplotlib重新加载字体。我们先来解决第一件事,这也是最彻底的一步。
matplotlib把它的缓存文件放在了一个固定的目录里。我们不需要去猜它在哪里,matplotlib提供了一个非常方便的函数来获取这个路径:


422

被折叠的 条评论
为什么被折叠?



