Matplotlib + Seaborn 中文字体显示问题:6种方案跨平台实测
背景:为什么 Matplotlib 显示中文会变成”豆腐块”?
如果你用过 Python 的 Matplotlib 或 Seaborn 做数据可视化,可能遇到过这样的问题:图表里的中文文字全部变成了一个个小方块,俗称”豆腐块”(tofu)。
这是为什么呢?
简单来说,Matplotlib 默认使用的字体不包含中文字符。就像你用英文打字机打中文,打出来当然是一堆乱码。解决方法就是告诉 Matplotlib:”请用一个支持中文的字体来显示文字。”
网上有很多解决方案,但哪种最靠谱?能不能跨平台(Windows、macOS、Linux)通用?我决定做个系统性测试。
测试方案
我设计了 6 种常见的解决方案,每种都用 GitHub Actions 在三个平台上自动运行,Python 版本统一使用 3.14。
| 方案 | 名称 | 原理 |
|---|---|---|
| 方法1 | rcParams 设置 | 在代码里直接告诉 Matplotlib 用什么字体 |
| 方法2 | matplotlibrc 配置文件 | 写一个配置文件,让 Matplotlib 每次启动都读取 |
| 方法3 | FontProperties | 手动指定字体文件路径 |
| 方法4 | addfont() | 把字体文件加载到 Matplotlib 的字体管理器 |
| 方法5 | 系统字体自动检测 | 让脚本自动找系统里的中文字体 |
| 方法6 | 下载开源字体 | 直接下载 Noto Sans CJK 字体使用 |
测试环境
- 平台:Windows (windows-latest)、macOS (macos-latest)、Ubuntu (ubuntu-latest)
- Python:3.14
- 库版本:Matplotlib + Seaborn(最新版)
- 自动化:GitHub Actions(18 个 job 并行运行)
测试结果
经过人工验证每个平台生成的 PNG 图片,结果如下:
| 方案 | Windows | macOS | Ubuntu | 结论 |
|---|---|---|---|---|
| 方法1 rcParams | ✅ 正常 | ✅ 正常 | ✅ 正常 | 推荐 |
| 方法2 matplotlibrc | ❌ 豆腐块 | ❌ 豆腐块 | ❌ 豆腐块 | 不推荐 |
| 方法3 FontProperties | ✅ 正常 | ✅ 正常 | ✅ 正常 | 推荐 |
| 方法4 addfont | ✅ 正常 | ✅ 正常 | ✅ 正常 | 推荐 |
| 方法5 系统字体 | ❌ 失败 | ❌ 失败 | ❌ 失败 | 不可用 |
| 方法6 Noto Sans | ✅ 正常 | ✅ 正常 | ✅ 正常 | 推荐 |
关键发现
-
matplotlibrc 配置文件方案全平台失败:这是网上很多教程推荐的方法,但实测在所有平台上都显示豆腐块。可能是因为配置文件的字体设置没有被正确加载。
-
系统字体自动检测方案不可用:这个方案的脚本在所有平台上都运行失败,可能是脚本本身的问题。
-
四种方案跨平台可用:rcParams、FontProperties、addfont()、下载开源字体,这四种方法在所有平台上都能正常显示中文。
-
不同方案可能使用不同字体:虽然都能正常显示,但不同方案/平台可能使用了不同的字体(如 SimHei、Noto Sans CJK 等),视觉效果可能略有差异。
推荐方案
方案1:rcParams 设置(最简单)
import matplotlib.pyplot as plt
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Noto Sans CJK SC', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
优点:代码最少,全局生效 缺点:需要系统安装了对应字体
方案4:addfont()(最可靠)
import matplotlib.pyplot as plt
from matplotlib import font_manager
# 加载字体文件
font_path = '/path/to/NotoSansCJKsc-Regular.otf'
font_manager.fontManager.addfont(font_path)
# 设置字体
plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']
plt.rcParams['axes.unicode_minus'] = False
优点:不依赖系统字体,字体文件可以打包分发 缺点:需要额外下载字体文件
方案6:下载开源字体(最可控)
直接下载 Noto Sans CJK 字体,然后用方案4的方法加载。
优点:字体开源免费,跨平台一致 缺点:需要额外步骤下载字体
总结
| 场景 | 推荐方案 |
|---|---|
| 快速原型/本地开发 | 方法1 (rcParams) |
| 需要跨平台一致 | 方法6 (下载 Noto Sans CJK) + 方法4 (addfont) |
| 项目需要打包分发 | 方法4 (addfont) + 内嵌字体文件 |
避坑提醒:
- ❌ 不要用 matplotlibrc 配置文件方案,实测全平台失败
- ❌ 不要依赖系统字体自动检测,脚本容易出错
- ✅ 优先使用 rcParams 或 addfont() 方案
测试仓库
完整的测试代码和 GitHub Actions 配置可以在以下仓库找到:
GitHub 仓库:ZhulongNT/mpl-chinese-font-test
Actions 运行记录:Run #26954523100
本文测试基于 Python 3.14、Matplotlib 和 Seaborn 最新版,测试时间 2026 年 6 月。如果你在使用过程中遇到问题,欢迎在 GitHub 仓库提 issue。