第一次用matplotlib画图时,发现所有中文标签都变成了方框,这个坑我踩过三次。matplotlib默认使用英文字体库,就像新电脑没装中文字体一样自然显示不了汉字。本质上这是字体配置问题,但背后涉及字符编码、字体回退机制、渲染引擎等多层技术栈。
在Linux系统中,matplotlib会优先查找系统字体路径(通常是/usr/share/fonts/),而Windows则搜索C:\Windows\Fonts目录。当找不到支持中文的字体时,会自动回退到DejaVu Sans等仅支持ASCII的字体。我曾用以下代码验证过:
python复制import matplotlib.font_manager as fm
print([f.name for f in fm.fontManager.ttflist if 'hei' in f.name.lower()])
最彻底的解决方式是修改matplotlib的配置文件matplotlibrc。这个文件通常位于:
用文本编辑器打开后,找到以下两行进行修改:
code复制font.family : Microsoft YaHei, sans-serif
font.sans-serif : Microsoft YaHei, SimHei, FangSong, KaiTi, STKaiti, STXihei, STHeiti
重要提示:修改前建议备份原文件,字体名称必须与系统已安装字体完全一致
如果不想修改全局配置,可以在代码中动态设置。推荐使用以下三种方式:
python复制plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] # Windows
plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei'] # Linux
python复制from matplotlib.font_manager import FontProperties
font = FontProperties(fname='/path/to/your/font.ttf', size=12)
plt.xlabel('X轴', fontproperties=font)
python复制import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = [font.name for font in fm.fontManager.ttflist if 'hei' in font.name.lower()]
不同操作系统需要配置不同的字体名称:
| 操作系统 | 推荐字体 | 备选字体 |
|---|---|---|
| Windows | Microsoft YaHei | SimHei, FangSong |
| macOS | PingFang SC | Hiragino Sans GB |
| Linux | WenQuanYi Zen Hei | Noto Sans CJK SC |
我曾用这个方案在Docker容器中成功显示中文:
dockerfile复制RUN apt-get update && apt-get install -y fonts-wqy-zenhei
修改配置后如果无效,可能需要清除字体缓存:
python复制fm._rebuild()
在Jupyter中需要额外配置:
python复制%matplotlib inline
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
保存PDF/SVG时需确保嵌入字体:
python复制plt.savefig('output.pdf', bbox_inches='tight',
metadata={'Creator':None, 'Producer':None},
fonttype=42)
如果系统缺少中文字体,可以手动安装:
sudo apt install fonts-wqy-zenhei验证字体是否生效:
python复制[f for f in fm.fontManager.ttflist if 'hei' in f.name.lower()]
我在实际项目中总结出一个万能检测脚本:
python复制def check_chinese_font():
available = [f.name for f in fm.fontManager.ttflist
if any(c in f.name.lower() for c in ['hei','song','kai'])]
if not available:
raise RuntimeError('未检测到中文字体,请安装微软雅黑、思源黑体等字体')
return available[0]
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 中文显示为方框 | 未配置中文字体 | 修改rcParams或matplotlibrc |
| 保存图片后中文消失 | 未嵌入字体 | 保存时设置fonttype=42 |
| 部分字符显示异常 | 字体缺少字形 | 更换更完整的字体如思源黑体 |
| Jupyter中不生效 | 内核未重启 | 重启kernel后重新运行 |
| Docker环境中文乱码 | 容器内缺少字体 | Dockerfile中安装字体包 |
最后分享一个血泪教训:在团队协作时,务必在项目README中注明字体依赖。我曾因忽略这点导致自动化报告生成失败,排查了整整两天才发现是CI服务器缺少中文字体。现在我的标准做法是在项目初期就通过代码自动检测字体环境:
python复制try:
plt.title('测试中文')
plt.close()
except RuntimeError as e:
print('中文显示异常,请执行安装命令:')
print('Linux: sudo apt install fonts-wqy-zenhei')
print('Windows: 请安装微软雅黑字体')