Matplotlib 中文乱码根源是默认字体不支持中文且未显式加载中文字体,需在创建 figure 前指定真实存在的字体路径并设 axes.unicode_minus=False 修复负号方块。

Matplotlib 中文乱码的根源在哪?
Matplotlib 默认字体不支持中文,遇到 plt.xlabel("时间") 这类含中文的调用时,会静默回退到无衬线英文字体(如 DejaVu Sans),结果要么显示方块、要么空白、要么报 Font family ['sans-serif'] not found 警告。这不是编码问题(UTF-8 已是默认),而是字体资源缺失 + 配置未显式指定。
- 必须手动指定一个系统中真实存在的中文字体文件路径,或注册字体名
- 不能只靠
plt.rcParams['font.sans-serif'] = ['SimHei']就完事——Windows 的 SimHei 在 macOS/Linux 上根本不存在 -
matplotlib.font_manager.findSystemFonts()可查本机可用字体路径,别凭经验硬写
一劳永逸解决中文+负号的三步实操
关键不是“改 rcParams”,而是让 Matplotlib 真正加载并信任中文字体,同时修复负号被渲染为方块的问题(本质是 Unicode 减号 U+2212 与 ASCII 减号 U+002D 混淆):
- 在绘图前插入以下代码块(推荐放在脚本开头或配置模块中):
import matplotlib.pyplot as plt import matplotlib # 强制使用 TrueType 字体,避免某些后端 fallback 失败 matplotlib.rcParams['pdf.fonttype'] = 42 matplotlib.rcParams['ps.fonttype'] = 42 </li></ul><h1>启用中文字体支持(以 macOS 为例,Linux/Windows 替换对应路径)</h1><p>zh_font_path = "/System/Library/Fonts/PingFang.ttc" # macOS 系统字体</p><h1>zh_font_path = "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc" # Ubuntu</h1><h1>zh_font_path = "C:/Windows/Fonts/msyh.ttc" # Windows 微软雅黑</h1><p>font_prop = matplotlib.font_manager.FontProperties(fname=zh_font_path) plt.rcParams['font.family'] = font_prop.get_name() plt.rcParams['axes.unicode_minus'] = False # 关键:让负号用 ASCII 减号显示,避免方块</p>
-
plt.rcParams['axes.unicode_minus'] = False必须设为False,设成True反而会让负号变方块 - 不要混用
font.sans-serif和font.family;后者优先级更高且更可靠 - 如果用 Jupyter,需重启内核才能使字体路径生效,仅
%matplotlib inline不够
保存图片时中文仍乱码?检查后端和格式
plt.savefig()出现乱码,90% 是后端不支持或格式限制导致的:
macOS UI 自动化技能包 —— 用 Python 控制你的 Mac下载让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
立即学习“Python免费学习笔记(深入)”;
- PDF/SVG 格式对字体嵌入要求高,务必确保
pdf.fonttype = 42(即 TrueType) - PNG 默认没问题,但若用 Agg 后端且未提前载入字体,仍可能 fallback
- 避免使用
plt.savefig("plot.pdf", bbox_inches='tight')时漏掉facecolor='white'——透明背景有时干扰字体渲染 - 若部署在 Docker 或无 GUI 环境,确认已安装中文字体包(如 Debian 系加装
fonts-wqy-microhei)并验证路径存在
多环境部署时字体路径怎么写才安全?
硬编码路径在跨平台项目里极易崩。稳妥做法是条件探测 + 回退:
- 用
matplotlib.font_manager.findfont()检测是否已有可用中文字体名(如"AR PL UKai CN") - 或遍历常见路径列表,用
os.path.exists()找第一个存在的字体文件 - 最简兜底:用
matplotlib.font_manager.FontProperties(family="sans-serif")并接受部分中文显示异常,总比全屏方块强
字体注册和负号开关这两件事,必须在创建任何 figure 之前完成。一旦
plt.figure()或plt.subplot()执行过,后续改 rcParams 对已生成对象无效。 -

















