Python Matplotlib图表中文乱码怎么解决及字体自定义

一只小鹿
一只小鹿
发布时间:2026-10-21| 5人浏览过
原创
在 Python 中使用 Matplotlib 绘图时,包含中文的标题、坐标轴标签和图例经常会变成空白矩形或方块(俗称“豆腐块”)。导致这一问题的根本原因是 Matplotlib 默认加载的西文字体未包含中文字形,同时坐标轴负号也会因为默认使用 Unicode 减号而失效。本文将先解析乱码机理,随后给出全局配置、项目级独立字体引入及缓存清理三套具体解决方案,帮助读者彻底解决中文显示与字体自定义需求。

一、Matplotlib 中文乱码成因与直观表现

初次在 Python 脚本中使用 plt.title("某城市月度气温走势") 或 plt.xlabel("月份") 时,生成的图表往往不会正常呈现汉字,而是在终端抛出一长串警告:UserWarning: Glyph 26576 missing from current font.。图表界面上对应的文字位置则被替换为一个或多个空心方框。

这是因为 Matplotlib 在初始化时,默认的字体族(font.family)指向 sans-serif(无衬线字体),其内部候选列表首位是 DejaVu Sans。这是一套为西文字符设计的开源字体,在其字库字形表(Glyph Table)中根本没有包含 CJK(中日韩)汉字的字符映射。当渲染引擎尝试根据 Unicode 码点绘制汉字时,找不到对应的矢量轮廓,只能使用缺字备用符号(即方块)代替。

除此之外,若图表坐标轴包含负数(例如气温 -5℃),负号经常也会同步变成方块。这并非中文专属问题,而是 Matplotlib 默认开启了 axes.unicode_minus = True。它会尝试使用 Unicode 编码 U+2212(Minus Sign 减号)而非 ASCII 标准的连字符 -(Hyphen-minus,ASCII 45)来绘制负号,许多中文字体库同样缺少该特殊减号符号,导致负号连带损坏。

Python Matplotlib图表中文乱码怎么解决及字体自定义
图 1:Matplotlib 默认字体查找链与乱码触发机制示意图

二、方法一:配置全局 rcParams(快捷有效)

针对日常数据分析、Jupyter Notebook 或个人电脑环境,最快见效的方式是通过 matplotlib.pyplot.rcParams 动态修改全局运行时参数。

不同操作系统内置的中文字体名称各不相同。如果在脚本中硬编码单一字体名称(例如只写 SimHei),代码在 Windows 上运行正常,但在 macOS 或 Linux 上又会因找不到该字体再次回退为乱码。因此推荐在 font.sans-serif 中传入一个包含多平台常见字体的优先列表:

import matplotlib.pyplot as plt

# 1. 设置中文字体优先回退列表(覆盖 Windows、macOS 及 Linux 常见字体)
plt.rcParams['font.sans-serif'] = [
    'PingFang SC',         # macOS 苹方
    'Microsoft YaHei',    # Windows 微软雅黑
    'SimHei',             # Windows 黑体
    'WenQuanYi Micro Hei',# Linux 文泉驿微米黑
    'Noto Sans CJK SC',   # 通用思源黑体
    'sans-serif'          # 兜底无衬线
]

# 2. 正常显示负号(解决负数变成方框的问题)
plt.rcParams['axes.unicode_minus'] = False

# 示例绘图验证
categories = ['一季度', '二季度', '三季度', '四季度']
values = [-12.5, 25.0, 18.2, -6.8]

fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(categories, values, color='#394957')
ax.set_title("季度净利润率变动(%)")
ax.set_ylabel("净利率")
ax.grid(axis='y', linestyle='--', alpha=0.5)

plt.show()

各大操作系统常见的中文字体名称对比如下表所示。在编写跨平台代码时,建议将目标平台的对应字体排在列表靠前位置:

操作系统 常用中文无衬线体名称 常用中文衬线/仿宋体名称 系统预装状态
Windows Microsoft YaHei、SimHei SimSun(宋体)、KaiTi 绝大多数版本默认预装
macOS PingFang SC、Heiti SC Songti SC、Kaiti SC 系统自带,无需安装
Linux (Ubuntu/Debian) WenQuanYi Micro Hei、Noto Sans CJK SC WenQuanYi Zen Hei 通常需 apt 安装 fonts-wqy-microhei

三、方法二:使用本地字体文件与 FontProperties(推荐项目级规范)

在商业项目、团队协作或部署到无桌面环境的 Linux Docker 容器时,全局依赖宿主机安装的字体往往脆弱不可靠。不同团队成员的机器环境各异,极易产生渲染差异或在 CI/CD 中断裂。

最稳健、工程化标准最高的方式是:将开源中文字体文件(如思源黑体 SourceHanSansSC-Regular.otf 或阿里普惠体 .ttf)直接存放在代码仓库的资源目录中,通过 matplotlib.font_manager.FontProperties 显式加载。

这种方式具有以下优势:

  • 零系统环境依赖:无论是本地 Windows、macOS 还是远程 Linux 服务器,只要 Python 能读取该文件,就能保证 100% 正确出图。
  • 完全不污染全局配置:可以为不同图表元素指定不同的字体与粗细,例如大标题用粗体,轴标签用细体。
  • 渲染效果跨平台绝对一致:字体度量完全统一,排版比例和行距在不同操作系统下完全吻合。
import os
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

# 1. 定位项目内的字体文件路径(支持 .ttf 与 .otf 格式)
# 建议将字体保存在例如 ./fonts/SourceHanSansSC-Regular.otf
current_dir = os.path.dirname(os.path.abspath(__file__)) if '__file__' in locals() else '.'
font_path = os.path.join(current_dir, "fonts", "SourceHanSansSC-Regular.otf")

# 2. 实例化字体属性对象,可单独设置字号
my_font = FontProperties(fname=font_path, size=11)
title_font = FontProperties(fname=font_path, size=14)

# 3. 依旧保留负号修正
plt.rcParams['axes.unicode_minus'] = False

# 4. 在具体绘图 API 中通过 fontproperties 参数传入
fig, ax = plt.subplots(figsize=(7, 4.5))
ax.plot(['1月', '2月', '3月', '4月'], [12, -4, 8, 15], marker='o', color='#AD8B58')

# 在需要显示中文的具体位置挂载字体
ax.set_title("月度指标监测数据", fontproperties=title_font, color='#394957', pad=12)
ax.set_xlabel("监控周期", fontproperties=my_font)
ax.set_ylabel("偏差数值(点)", fontproperties=my_font)

for label in ax.get_xticklabels() + ax.get_yticklabels():
    label.set_fontproperties(my_font)

plt.show()
Python Matplotlib图表中文乱码怎么解决及字体自定义
图 2:Matplotlib 中文解决方案决策路径示意图

四、字体配置作用域与层级优先级

为了在复杂图表中实现精细化的视觉排版,需要理解 Matplotlib 内部对字体的多层覆盖机制。从最底层的全局默认值,到最高优先级的单个元素定制,优先级从低到高排列如下:

  1. 系统与库默认配置:Matplotlib 安装目录下的 matplotlibrc 静态配置文件。
  2. 运行时全局会话层(rcParams):在当前脚本中执行的 plt.rcParams['font.sans-serif']。所有在此之后创建的 Figure 和 Axes 均继承该属性。
  3. 文本参数字典层(fontdict):调用 ax.set_title(..., fontdict={'family': '...', 'size': 16})。只对当前文本对象生效,覆盖全局字体族设置。
  4. 独立字体属性对象(FontProperties):直接传递 fontproperties=...。这是权重最高的方式,直接绕过字体管理器的系统名称映射,强行绑定指定字体文件或族名。
Python Matplotlib图表中文乱码怎么解决及字体自定义
图 3:Matplotlib 字体配置作用域与层级关系示意图

五、排查技巧:新装字体识别失败与缓存清理

有时用户虽然在操作系统中下载安装了中文字体(例如在 Windows 安装了思源黑体,或在 Linux 下把字体文件复制到了 /usr/share/fonts/),并且也在 rcParams 里配置了该字体名字,但绘制图表时依然出现乱码。

这通常是因为 Matplotlib 的字体缓存机制。在初次导入该库时,Matplotlib 会全面扫描系统字体目录并生成一个名为 fontlist-vXXX.json 的索引缓存文件。随后为了加快加载速度,它只会查询此缓存而不会每次重新扫描磁盘。新安装的字体如果没有触发缓存重建,就会被视作不存在。

1. 查看当前已成功识别的中文字体列表

可以通过运行以下轻量脚本,快速打印出当前 Python 环境下 Matplotlib 真正识别到了哪些中文字体:

import matplotlib.font_manager as fm

# 获取 Matplotlib 字体管理器中所有已注册字体的名称
available_fonts = sorted({f.name for f in fm.fontManager.ttflist})

# 筛选包含常见中文标识或关键词的字体
chinese_keywords = ['SC', 'Sim', 'Hei', 'Song', 'Kai', 'Ming', 'YaHei', 'Noto', 'WenQuanYi']
detected_chinese = [f for f in available_fonts if any(k.lower() in f.lower() for k in chinese_keywords)]

print("当前已识别的中文字体名称(可直接填入 rcParams):")
for name in detected_chinese:
    print(f" - {name}")

2. 清除字体缓存缓存文件

如果列表中没有新安装的字体,只需要定位并删除 Matplotlib 缓存目录。在 Python 中直接获取缓存路径:

import matplotlib

# 输出缓存所在的系统真实路径
print("缓存目录:", matplotlib.get_cachedir())

在终端中进入该目录,找到并删除以 fontlist- 开头、后缀为 .json 的文件(例如 fontlist-v330.json)。再次运行 Python 绘图代码时,Matplotlib 会重新全盘扫描系统字体,新字体便能正常加载。

六、全流程排查四步法总结

掌握了成因、方案与排查手段后,面对任何环境下的中文乱码问题,只需按以下四步稳妥推进:

  1. 第一步(明确目标字体):优先检查系统是否已有中文字体名;若需要严谨部署,则将 .ttf/.otf 字体放进代码目录。
  2. 第二步(规范配置注入):根据是个人使用还是工程部署,选择 rcParams['font.sans-serif'] 列表回退,或使用 FontProperties(fname=...)。
  3. 第三步(关闭负号转换):务必加入 plt.rcParams['axes.unicode_minus'] = False,防止减号损坏。
  4. 第四步(缓存刷新与出图验证):若字体未生效,利用 get_cachedir() 清理 fontlist 缓存并运行测试出图。
Python Matplotlib图表中文乱码怎么解决及字体自定义
图 4:中文乱码解决与自定义字体排查四步法总结
实用建议:在构建面向生产的数据看板、报表自动化生成任务或公开绘图组件时,始终优先采用“字体文件内置于项目 + FontProperties 引入 + axes.unicode_minus = False”的组合。这能从根源上杜绝跨平台系统差异带来的各种缺字和方框隐患。
相关标签:

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

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 算法库。