Python matplotlib绘图中文显示乱码怎么解决

夏知夏
夏知夏
发布时间:2026-11-15| 5人浏览过
原创

详细讲解 Python 中 Matplotlib 绘图时中文显示为乱码或方块的根本成因,并提供运行时代码配置、FontProperties 局部引入、matplotlibrc 全局配置文件修改三种解决策略,附带负号异常修复与完整可运行代码。

假设你在 Python 环境中刚完成一组数据的统计,准备使用 Matplotlib 绘制一条趋势曲线,并为图表加上中文标题“月度温度变化趋势”和坐标轴标签“月份”与“摄氏度”。运行代码后,弹出的图表窗口中原本应该显示中文的位置却出现了一排空白方块(俗称“豆腐块”),控制台同时输出了 UserWarning: Glyph 26376 missing from current font 警告。这是初学者与数据分析人员在使用 Matplotlib 时极为普遍的现象。

解决这个问题的核心结论非常明确:Matplotlib 默认使用的英文字体库中不包含中文字形数据,只需在导入模块后,通过 plt.rcParams['font.sans-serif'] 指定系统内置的中文字体名称(例如 Windows 下的 SimHei 或 macOS 下的 PingFang SC),并同步将 plt.rcParams['axes.unicode_minus'] 设置为 False 避免负号异常,即可彻底恢复中文的正常渲染。

一、问题根源:为什么中文会显示为方块

Matplotlib 的文本排版引擎在绘制字符时,会根据配置中的无衬线字体列表(font.sans-serif)依次向底层系统请求字形数据。在默认安装状态下,该列表排在最前面的是 DejaVu Sans、Bitstream Vera Sans 等开源英文字体。

这些英文字体只收录了 ASCII 编码和部分拉丁语系的字符轮廓,根本没有收录 CJK(中日韩统一表意文字)字形。当文本引擎遇到汉字对应的 Unicode 编码时,无法在首选字体中找到对应的轮廓信息,只得输出一个默认的占位空心方块,并在控制台中记录缺失字形(Glyph missing)的告警信息。

Python matplotlib绘图中文显示乱码怎么解决
图 1:Matplotlib 默认文本渲染机制与中文字形缺失成因

二、快速解决:运行时代码注入配置(推荐)

对于大多数日常脚本和 Jupyter Notebook 数据探索场景,最直接有效的方式是在脚本开头修改 matplotlib.pyplot.rcParams 运行时参数。这种方法无需管理员权限,也不修改环境底层文件。

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

不同操作系统内置的中文字体名称存在差异。配置时,需提供当前操作系统内已正确安装的中文字体名称:

操作系统 常用中文字体名称 字体中文名称
Windows SimHei、Microsoft YaHei 黑体、微软雅黑
macOS PingFang SC、Arial Unicode MS、Heiti TC 苹方-简、Arial Unicode、黑体-繁
Linux (Ubuntu / CentOS) WenQuanYi Micro Hei、Noto Sans CJK SC 文泉驿微米黑、思源黑体

注意:在配置字体列表时,建议按顺序填入多个操作系统的中文字体。Matplotlib 会按照先后顺序向后查找,只要其中一个字体存在即可生效,从而提高脚本的跨平台兼容性。

2. 完整可运行代码示例

以下示例展示了如何在代码头部加入字体与负号配置,并绘制一张包含中文标题、轴标签及负数坐标的图表:

import matplotlib.pyplot as plt

# 步骤一:设置中文字体回退列表(兼顾 Windows、macOS 与 Linux)
plt.rcParams['font.sans-serif'] = [
    'SimHei',             # Windows 黑体
    'PingFang SC',        # macOS 苹方
    'Microsoft YaHei',    # Windows 微软雅黑
    'WenQuanYi Micro Hei' # Linux 文泉驿
]

# 步骤二:解决负号 '-' 显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False

# 步骤三:构建测试数据并绘图
months = ['1月', '2月', '3月', '4月', '5月', '6月']
temperatures = [-5, -2, 4, 12, 19, 24]

plt.figure(figsize=(8, 4.5))
plt.plot(months, temperatures, marker='o', color='#2563eb', linewidth=2)

# 添加中文标题与坐标轴说明
plt.title('上半年平均气温变化走势', fontsize=14)
plt.xlabel('月份', fontsize=11)
plt.ylabel('气温(℃)', fontsize=11)
plt.grid(True, linestyle='--', alpha=0.6)

plt.show()
Python matplotlib绘图中文显示乱码怎么解决
图 2:运行时代码配置中文与负号四步实施流程

三、局部指定:使用 FontProperties 精细控制

如果你编写的代码需要打包分发给其他用户,或者图表中的不同元素需要分别指定不同的中文字体(如标题用黑体、注释用楷体),修改全局 rcParams 可能不够灵活。此时推荐使用 matplotlib.font_manager.FontProperties。

这种方式允许直接指定本地字体文件路径(.ttf 或 .otf),无需依赖宿主操作系统中是否已经注册该字体名:

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

# 方式 A:指定操作系统内已注册的字体名称
font_title = FontProperties(family='SimHei', size=14, weight='bold')
font_label = FontProperties(family='SimHei', size=10)

# 方式 B:直接指定字体文件的物理路径(支持打包携带自定义 ttf)
# font_custom = FontProperties(fname='./fonts/SourceHanSansSC-Regular.otf', size=12)

x = [1, 2, 3, 4]
y = [10, 25, 18, 30]

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, y, marker='s', color='#10b981')

# 在具体的文本接口中显式传入 fontproperties 参数
ax.set_title('核心业务指标增长情况', fontproperties=font_title)
ax.set_xlabel('季度', fontproperties=font_label)
ax.set_ylabel('数值(万元)', fontproperties=font_label)

plt.show()

四、全局永久生效:修改 matplotlibrc 配置文件

如果你长期在固定的本地机器或服务器上开发,不希望每次新建脚本都重复书写三行配置代码,可以直接修改 Matplotlib 的底层配置文件 matplotlibrc。

1. 获取配置文件与缓存路径

在 Python 终端中执行以下两行代码,打印出配置文件的物理存储位置与字体缓存目录:

import matplotlib

# 获取当前正在生效的配置文件路径
print("配置文件位置:", matplotlib.matplotlib_fname())

# 获取字体缓存目录
print("缓存目录位置:", matplotlib.get_cachedir())

2. 修改配置项内容

用文本编辑器打开打印出的 matplotlibrc 文件,搜索并修改以下两处配置(去掉行首的 # 注释):

# 1. 在 font.sans-serif 前面加上中文字体名称
font.sans-serif: SimHei, DejaVu Sans, Bitstream Vera Sans, sans-serif

# 2. 将 unicode_minus 改为 False,防止负号显示为方框
axes.unicode_minus: False

3. 清除字体缓存并重新加载

Matplotlib 在启动时会读取缓存文件(例如 fontlist-v330.json)以加快字体查找。修改配置或向系统新增字体后,必须手动删除缓存目录下的缓存文件,否则新配置不会立即生效。

删除 matplotlib.get_cachedir() 目录下的所有文件后,重启 Python 进程,Matplotlib 将会自动扫描并重新构建字体缓存。

Python matplotlib绘图中文显示乱码怎么解决
图 3:Matplotlib 三大中文字体支持方案多维度横向对比

五、常见问题排查清单

1. 为什么配置了中文字体后,负号变成了小方块?

在默认配置下,Matplotlib 使用 Unicode 的负号字符(MINUS SIGN: U+2212)来绘制坐标轴上的负刻度。部分中文字体中虽然包含了汉字,但并未正确实现这个特殊的数学负号字符,导致负号位置再次出现方块。

解决方法是设置 plt.rcParams['axes.unicode_minus'] = False。该参数指示 Matplotlib 放弃 Unicode 负号,转为直接使用标准 ASCII 连字符(HYPHEN-MINUS: U+002D),所有字体均能无误呈现该字符。

2. 如何排查当前系统到底有哪些可用中文字体?

如果你不确定当前计算机安装了哪些可以被 Matplotlib 识别的中文字体,可以运行以下代码片段遍历字体管理器:

import matplotlib.font_manager as fm

# 扫描系统中所有已安装并能被识别的字体
available_fonts = []
for font in fm.fontManager.ttflist:
    # 过滤出名称中包含中文特征或常用中文字体名的项
    name = font.name
    if any(keyword in name.lower() for keyword in ['hei', 'song', 'kai', 'pingfang', 'yahei', 'cjk', 'micro hei']):
        available_fonts.append((font.name, font.fname))

# 去重并输出前 10 个可用字体
unique_fonts = sorted(list(set(available_fonts)))
print(f"找到 {len(unique_fonts)} 个可用中文字体:")
for name, path in unique_fonts[:10]:
    print(f"名称: {name:<20} 路径: {path}")
Python matplotlib绘图中文显示乱码怎么解决
图 4:Matplotlib 中文乱码故障排查与修复决策流程

六、总结

解决 Matplotlib 中文显示乱码的核心在于“替换无衬线字体的默认查找项”。对于日常脚本分析,在代码首部声明 plt.rcParams['font.sans-serif'] = ['SimHei', 'PingFang SC'] 与 plt.rcParams['axes.unicode_minus'] = False 是开发成本最低、最不易出错的方案;而在涉及图表组件交付或多系统共享时,使用 FontProperties 显式指定物理字体文件能提供最稳健的跨平台保障。

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

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