Python matplotlib绘图中文显示方框乱码的解决方法

凌晨两点半
凌晨两点半
发布时间:2026-10-23| 6人浏览过
原创

在使用 Python 的 matplotlib 库绘制图表时,凡是包含中文字符的标题、轴标签或图例文本,默认情况下常常会变成一个个无法辨识的空心“□”(方框),终端还会伴随抛出诸如 Glyph ... missing from current font 的警告信息。造成该现象的根本原因并非 matplotlib 不支持中文,而是其底层默认采用的西文字体(DejaVu Sans)缺乏中文字形矢量。解决该问题主要有两种标准路径:一是在脚本中通过 plt.rcParams 进行动态指定(即配即用、适合跨机器与数据分析),二是修改全局 matplotlibrc 配置文件并清除字体缓存(单机一次配置、永久生效)。同时,还需配合关闭 Unicode 负号设置,以防负数刻度同样退化为方框。

Python matplotlib绘图中文显示方框乱码的解决方法
图 1:Matplotlib 字符渲染管线及方框缺失(Glyph Missing)产生机理

一、为什么会出现“方框”与负号异常?

很多初学者误以为 Python 或者 matplotlib 内部缺少对中文的编解码支持,进而试图对文字进行转码或频繁更换编码格式。实际上,文字在 Python 3 中以 Unicode 字符串存储,编码传递本身没有任何损耗。问题出在图形后端的“矢量字形光栅化”环节。

1. 缺少中文字形(Glyphs)

matplotlib 的样式配置字典 rcParams['font.family'] 默认设置为 'sans-serif',而其对应的候选字体列表 font.sans-serif 中,排在首位的是开源英文字体 DejaVu Sans。该字体仅收录了拉丁字母、希腊字母以及基础标点,完全不包含 CJK(中日韩统一表意文字)字形。当渲染引擎尝试按照汉字码位从当前字体中提取轮廓时,找不到对应矢量图形,就会回退渲染为一个代表缺失的空白矩形(业内常称“.notdef”或 Tofu 豆腐块),并在控制台输出如下警告:

UserWarning: Glyph 25968 (\N{CJK UNIFIED IDEOGRAPH-6570}) missing from font(s) DejaVu Sans.
  plt.tight_layout()

2. 坐标轴负号(Minus Sign)显示异常

解决中文显示之后,往往会立刻撞见另一个连锁问题:包含负数的坐标刻度(如 -10、-20)中的减号变成了方框。这是因为 matplotlib 默认启用了 axes.unicode_minus = True,它会使用标准的 Unicode 负号字符(U+2212,MINUS SIGN)而非键盘上的 ASCII 减号(U+002D,HYPHEN-MINUS)。然而,包括“中易黑体”(SimHei)在内的许多传统中文字体并未正确收录 U+2212 字符,从而导致负号再度退化为方框。因此,设置中文字体的同时,必须将该配置项设为 False。

Python matplotlib绘图中文显示方框乱码的解决方法
图 2:在脚本内通过 rcParams 修复中文及负号的推荐四步流程

二、解决方法一:脚本内动态配置 rcParams(推荐方案)

对于绝大多数数据分析脚本、Jupyter Notebook 或团队协作项目,最实用、侵入性最小的做法是在导入 matplotlib.pyplot 之后,直接通过 plt.rcParams 动态指定系统已有的中文字体名称。这种方式无需操作系统管理员权限,也不依赖本地特定的安装路径。

1. 各操作系统常见中文字体名称

不同操作系统内置的中文字体名称不尽相同。如果硬编码了 Windows 的字体名称(如 SimHei),代码放到 macOS 或 Linux 服务器上运行时依然会找不到字体。以下是各系统最常见的预装字体族名:

操作系统 推荐字体名称(Font Family) 对应中文名称 特性说明
Windows SimHei, Microsoft YaHei 黑体、微软雅黑 Windows 几乎 100% 默认自带,字形饱满易读
macOS PingFang SC, Arial Unicode MS, Heiti SC 苹方、黑体-简 现代 macOS 标配 PingFang SC,字符集支持完善
Linux / Ubuntu WenQuanYi Micro Hei, Noto Sans CJK SC 文泉驿微米黑、思源黑体 云服务器或 Docker 容器通常需要预装对应包

2. 编写兼容多系统的通用代码

为了让同一份 Python 代码在不同机器上均能正常展示中文,推荐向 font.sans-serif 传递一个字体名称列表。matplotlib 会按顺序自左向右查找系统已安装的字体,一旦匹配成功即使用该字体,实现自动优雅降级:

import matplotlib.pyplot as plt

# 1. 设置中文字体候选列表(按系统常用顺序排布)
plt.rcParams['font.sans-serif'] = [
    'PingFang SC',       # macOS 首选
    'Microsoft YaHei',   # Windows 微软雅黑
    'SimHei',            # Windows 黑体
    'Noto Sans CJK SC',  # Linux 思源黑体
    'WenQuanYi Micro Hei', # Linux 文泉驿
    'sans-serif'         # 最终回退西文字体
]

# 2. 正常显示负号(避免减号变为方框)
plt.rcParams['axes.unicode_minus'] = False

# 3. 示例绘图验证
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot([-3, -1, 0, 2, 4], [-9, -1, 0, 4, 16], marker='o', color='#8A9478')
ax.set_title("年度数据增长趋势示例", fontsize=14)
ax.set_xlabel("时间区间(相对基准月)", fontsize=11)
ax.set_ylabel("指标变化值", fontsize=11)
ax.grid(True, linestyle='--', alpha=0.5)

plt.tight_layout()
plt.show()

3. 局部指定字体:FontProperties 方法

在某些严谨的排版需求中,如果不想改变全局的 rcParams,或者需要图表中英文字体分离(例如英文用 Helvetica,仅标题单独使用中文字体),可以使用 matplotlib.font_manager.FontProperties 进行局部精确传参:

from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt

# 方式 A:通过系统已安装字体名称初始化
my_font = FontProperties(family='SimHei', size=12)

# 方式 B:直接指定本地 .ttf / .otf 字体文件的绝对路径(在容器或离线部署时极其实用)
# my_font = FontProperties(fname='/path/to/simhei.ttf', size=12)

fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
# 仅针对该文本对象传入 fontproperties
ax.set_title("局部指定的中文标题", fontproperties=my_font)
plt.show()
Python matplotlib绘图中文显示方框乱码的解决方法
图 3:运行时动态配置与全局永久配置的场景对比与权衡

三、解决方法二:修改 matplotlibrc 配置文件(永久生效)

如果日常在自己的个人开发机上进行大量本地绘图,不希望每次新建脚本都反复书写 plt.rcParams,可以通过修改 matplotlib 的全局配置文件 matplotlibrc 实现开箱即用。

1. 查询当前配置文件与缓存路径

在 Python 交互式环境中执行以下命令,获取当前环境使用的配置文件位置以及字体缓存目录:

import matplotlib
print("配置文件路径:", matplotlib.matplotlib_fname())
print("字体缓存目录:", matplotlib.get_cachedir())

通常输出形如:

  • 配置文件:.../site-packages/matplotlib/mpl-data/matplotlibrc
  • 缓存目录:~/.cache/matplotlib(Linux/macOS)或 C:\Users\<用户名>\.matplotlib(Windows)

2. 修改 matplotlibrc 关键参数

使用文本编辑器打开上述 matplotlibrc 文件,找到以下两行配置。注意:默认情况下这两行前方通常带有注释符 #,必须将开头的 # 删除,并在参数最前端添加系统支持的中文字体:

# 找到 font.sans-serif 这一行,去掉开头的 #,并在冒号后加入 SimHei 或对应中文字体名称
font.sans-serif: SimHei, DejaVu Sans, Bitstream Vera Sans, ...

# 找到 axes.unicode_minus 这一行,去掉开头的 #,并将其修改为 False
axes.unicode_minus: False
关键操作提醒:必须清理字体缓存

修改完 matplotlibrc 后,如果直接运行脚本,往往会发现修改并未生效。这是因为 matplotlib 在初次运行时会扫描系统字体并生成形如 fontlist-v330.json 的索引缓存文件。只要缓存存在,matplotlib 就不会重新扫描配置文件。必须前往 matplotlib.get_cachedir() 所在路径,将该缓存目录内的全部文件删除(或直接删除该缓存文件夹),随后重启 Python 解释器或 Jupyter 内核。

Python matplotlib绘图中文显示方框乱码的解决方法
图 4:常见乱码现象分类诊断与速查决策卡片

四、常见容易混淆的说法与进阶避坑

1. 误区辨析:“把字体文件拷入 matplotlib/fonts/ttf 目录”为什么不推荐?

网络上不少早期教程建议“下载 SimHei.ttf 文件,直接粘贴进 Python 安装包下的 mpl-data/fonts/ttf 目录”。这种做法在原理上有其依据(将字体直接提供给库自带的搜索根路径),但在实际工程维护中存在明显缺陷:

  • 依赖虚拟环境生命周期:一旦使用 pip install --upgrade matplotlib 升级库,或者新建虚拟环境(venv / conda),该手动拷入的字体文件就会彻底消失。
  • 仍需手工清缓存:很多读者照做后发现依然无效,原因依然是没有执行删除缓存的步骤。实际上,只要操作系统自身已安装该字体,系统全局路径中的字体完全可以被 matplotlib 自动检索到,根本不需要去篡改 Python 第三方包的内部文件。

2. Seaborn 样式覆盖问题

如果在项目中同时使用了 seaborn 库,常会出现“前脚设置了中文字体,后脚调用 sns.set_theme() 或 sns.set_style() 后中文再度变回方框”的怪现象。这是因为 Seaborn 在应用内置主题时,会主动重置 plt.rcParams。正确的顺序是在调用任何 Seaborn 主题初始化函数之后,再行执行字体配置:

import seaborn as sns
import matplotlib.pyplot as plt

# 先设置 Seaborn 样式风格
sns.set_theme(style="whitegrid")

# 后覆盖字体相关参数(切忌顺序颠倒)
plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC', 'sans-serif']
plt.rcParams['axes.unicode_minus'] = False

3. Jupyter Notebook 运行时注意

在 Jupyter Notebook 中,plt.rcParams 的改动仅对当前活跃的 Python 内核进程有效。若修改了外部的 matplotlibrc 配置文件或安装了新的系统字体,仅在 Cell 中重新运行 import matplotlib 是无效的,必须点击顶部菜单栏的 Kernel -> Restart Kernel 重启内核,使配置与字库完成重新加载。

五、生产环境直接复制模板

为了便于在日常编写脚本时快速调用,以下是一段经过生产环境与跨平台验证的精简模版:

import matplotlib.pyplot as plt

# 跨平台中文字体自适应配置模板
plt.rcParams.update({
    'font.sans-serif': ['PingFang SC', 'Microsoft YaHei', 'SimHei', 'Noto Sans CJK SC', 'sans-serif'],
    'axes.unicode_minus': False
})

# 后续正常编写绘图逻辑即可
# plt.plot(...)
# plt.title("中文标题正常显示")

通过掌握上述字体匹配原理,配合跨平台字体列表与负号开关设置,即可彻底解决 matplotlib 绘图中的中文方框乱码问题。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。