Matplotlib中文乱码根本原因是找不到可用中文字体或fallback失效,需检查系统字体、显式指定真实字体名、设置unicode_minus为False,并优先用FontProperties指向绝对路径字体文件。

plt.rcParams 设置中文后图表仍乱码?检查字体路径和 fallback
根本原因不是没设 plt.rcParams,而是 Matplotlib 找不到能渲染中文的字体,或者 fallback 机制没生效。Linux/macOS 默认不带 SimHei、Microsoft YaHei 这类 Windows 字体,matplotlib.font_manager.findfont 会悄悄回退到一个不支持中文的字体(比如 DejaVu Sans),表面没报错,但汉字全变方框或空格。
- 先确认系统里真有可用中文字体:
fc-list :lang=zh(Linux/macOS)或打开字体册搜“思源黑体”“Noto Sans CJK” - 在
plt.rcParams中显式指定已知存在的字体名,不要写“SimHei”就以为 Windows 一定能用——得看实际安装名,比如'Noto Sans CJK SC'或'Source Han Sans CN' - 必须加
plt.rcParams['axes.unicode_minus'] = False,否则负号显示为方块(这是高频静默坑)
pandas.DataFrame.plot() 不继承 plt.rcParams?手动传 fontproperties
pandas 的绘图封装(基于 matplotlib)默认不主动读取 plt.rcParams 中的字体设置,尤其在较新版本(1.5+)中更倾向使用 rcParams 的子集,中文字段容易被忽略。直接改全局配置不一定生效,得“双重保险”。
- 对单个图表,用
plt.xlabel(..., fontproperties=...)或ax.set_title(..., fontproperties=...)显式传入FontProperties - 推荐方式:提前构造一个复用的
font对象:from matplotlib.font_manager import FontProperties font = FontProperties(fname='/path/to/NotoSansCJKsc-Regular.otf') # 确保路径真实存在
- 绘图后所有文本调用统一传
fontproperties=font,比反复改 rcParams 更可控
Windows 上用 SimHei 却报错找不到字体?别硬编码字体名
Windows 系统里 'SimHei' 看似合理,但 Matplotlib 实际匹配的是字体文件里的「真实名称」(Full Name),不是文件名。很多用户把 simhei.ttf 拷进去,却用 fname 指向它,结果因字体元数据不全而失败。
- 不要依赖
fname+ 系统字体名混用;优先用FontProperties的fname参数指向具体 .ttf/.otf 文件(绝对路径) - 验证字体是否加载成功:
FontProperties(fname='xxx.ttf').get_name()应返回非空字符串 - 若坚持用系统字体名,查真实名称:
[f.name for f in matplotlib.font_manager.fontManager.ttflist if 'simhei' in f.name.lower()]
中文显示正常但图表变慢?字体缓存未预热
首次调用含中文的绘图时,Matplotlib 会扫描字体、构建 cache,卡顿明显,尤其在 Jupyter 或 Web 后端环境。这不是 bug,是设计使然——但它会在你调试时反复触发,显得像性能问题。
- 启动脚本开头加一句
import matplotlib; matplotlib.use('Agg')(非交互后端),再执行一次plt.figure(); plt.close(),强制触发字体发现与缓存 - 避免在循环里反复新建
FontProperties实例;复用同一个对象 - 导出 PDF/SVG 时中文正常,但 PNG 出乱码?检查后端是否支持字体嵌入(
Agg支持,Qt5Agg可能受限)
字体这件事,本质是 Matplotlib 在运行时做的一次“字体协商”,不是开关一开就完事。路径、名称、缓存、后端,四个点只要一个断掉,中文就悄无声息地消失。最稳的方式,永远是亲手指定一个你亲眼见过、能 ls 出来的字体文件。










