跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何解决Python绘图时中文字体显示乱码_配置matplotlib字体路径

根本原因是matplotlib默认不加载系统中文字体且字体缓存未识别可用中文字体;需手动设置font.sans-serif、禁用mathtext.fontset、设axes.unicode_minus=False,并强制刷新字体缓存或显式添加字体文件。 matplotlib绘图中文显示为方块或问号 根本原因是 matplotlib 默认不加载系统中文字体,且其内部字体缓存未识别可用的中文字体路径。即使系统有 SimHei、Noto Sans CJK 或 Source Han Sans 等字体,
plt.show()
仍可能渲染成方块(□)或空格。 手动指定 font.sans-serif 并禁用 mathtext.fontset 最直接有效的做法是修改 matplotlib 的运行时配置,而非改全局配置文件(容易被覆盖或失效):
import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei', 'KaiTi', 'FangSong', 'Microsoft YaHei', 'Noto Sans CJK SC', 'Source Han Sans CN'] plt.rcParams['axes.unicode_minus'] = False # 解决负号'−'显示为方块的问题 plt.rcParams['mathtext.fontset'] = 'stix' # 避免启用 mathtext 导致字体 fallback 失败
列表中字体名必须与系统实际安装的字体名称完全一致(大小写敏感),可用
fc-list :lang=zh
(Linux/macOS)或 PowerShell 中
[System.Drawing.Text.InstalledFontCollection]::new().Families
(Windows)查真实名称 把常用中文字体按优先级从左到右排列,matplotlib 会逐个尝试,第一个能加载的即生效
axes.unicode_minus=False
是必须项,否则负号会被当成数学符号走 mathtext 渲染路径,而 mathtext 不支持中文字体 验证字体是否真正加载成功 仅设
font.sans-serif
不代表字体已就绪——matplotlib 会在首次绘图时构建字体缓存,若缓存损坏或路径不可读,仍会回退到无中文支持的字体。 强制刷新字体缓存:
import matplotlib.font_manager as fm; fm._rebuild()
(执行后重启 Python 进程才完全生效) 检查当前生效字体:
print([f.name for f in fm.fontManager.ttflist if 'simhei' in f.name.lower() or 'sans' in f.name.lower()])
打印实际用于渲染的字体:
print(plt.rcParams['font.sans-serif'][0])
,再配合
plt.title('测试中文')
+
plt.show()
观察是否真显示 在 Docker 或无 GUI 环境中渲染中文图 服务器环境常缺字体文件和 X11 支持,
Agg
后端无法访问系统字体目录,直接报
findfont: Font family ['sans-serif'] not found
。 Python 3.14.3 微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。 下载 立即学习 “ Python免费学习笔记(深入) ”; 必须提前复制字体文件(如
simhei.ttf
)到项目目录,例如
./fonts/SimHei.ttf
用
fm.fontManager.addfont()
注册:
fm.fontManager.addfont('./fonts/SimHei.ttf')
,再设
rcParams['font.sans-serif'] = ['SimHei']
确保后端为非交互式:
import matplotlib; matplotlib.use('Agg')
必须放在
import pyplot
之前 避免使用
plt.show()
,改用
plt.savefig('out.png', bbox_inches='tight', dpi=150)
最容易被忽略的是:字体名 ≠ 文件名,也 ≠ 控制面板里看到的“显示名称”;同一个字体在不同系统上注册的
f.name
可能完全不同。不要依赖猜测,一定要用
fm.fontManager.ttflist
实际枚举并匹配。

相关文章