Matplotlib 绘制图表时,如果标题、坐标轴名称、图例或注释包含中文,常见的问题是中文字符显示为方框、乱码,甚至完全无法显示。这类问题通常不是 Matplotlib 本身不支持中文,而是当前环境没有配置合适的中文字体。
解决 Matplotlib 中文显示问题,核心就是找到系统中可用的中文字体,并通过 rcParams 或 FontProperties 告诉 Matplotlib 使用该字体。
一、为什么 Matplotlib 中文会显示异常
Matplotlib 默认字体通常是 DejaVu Sans,这款字体能够很好地覆盖英文、数字以及大量常见符号,但并不完整支持中文字符。
例如执行下面的代码:
Python运行import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [10, 25, 18, 32, 40] plt.plot(x, y) plt.title("销售数据趋势") plt.xlabel("月份") plt.ylabel("销售额") plt.show()
如果运行环境没有合适的中文字体,就可能出现类似下面的现象:
UserWarning: Glyph xxxx missing from current font.
最终图表中的中文可能变成:
□□□□□□
或者显示成无法识别的符号。
因此,问题的关键并不是修改字符串编码,而是为 Matplotlib 指定支持中文的字体。
二、最简单的解决方法
如果系统中已经安装了中文字体,可以直接通过 plt.rcParams 设置字体。
例如 Windows 系统通常可以使用微软雅黑:
Python运行import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] plt.rcParams["axes.unicode_minus"] = False x = [1, 2, 3, 4, 5] y = [10, 25, 18, 32, 40] plt.plot(x, y) plt.title("销售数据趋势") plt.xlabel("月份") plt.ylabel("销售额") plt.show()
其中:
Python运行plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
用于指定 Matplotlib 的无衬线字体。
而:
Python运行plt.rcParams["axes.unicode_minus"] = False
用于解决坐标轴负号显示异常的问题。
这两个配置经常一起使用。
三、不同操作系统应该选择什么字体
不同操作系统默认安装的中文字体并不相同,因此不要直接照搬某个系统的字体名称。
Windows
Windows 常见中文字体包括:
Microsoft YaHei SimHei SimSun KaiTi FangSong
例如:
Python运行plt.rcParams["font.sans-serif"] = ["SimHei"]
也可以使用:
Python运行plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
通常微软雅黑的显示效果比较适合普通数据可视化。
macOS
macOS 可以尝试:
Python运行plt.rcParams["font.sans-serif"] = ["Arial Unicode MS"]
部分 macOS 环境也可以使用:
PingFang SC Heiti SC STHeiti
例如:
Python运行plt.rcParams["font.sans-serif"] = ["PingFang SC"]
实际使用时仍然建议先确认字体是否存在。
Linux
Linux 环境中是否能够显示中文,取决于系统安装的字体。
常见选择包括:
Noto Sans CJK SC Noto Sans CJK CN WenQuanYi Zen Hei SimHei
例如:
Python运行plt.rcParams["font.sans-serif"] = ["Noto Sans CJK SC"]
如果服务器是精简安装的 Linux,可能根本没有中文字体,这时需要额外安装字体。
四、如何查看 Matplotlib 能使用哪些字体
如果不确定当前环境有哪些字体,可以通过 Matplotlib 查询。
Python运行from matplotlib.font_manager import fontManager for font in fontManager.ttflist: print(font.name)
运行后会得到类似:
DejaVu Sans Liberation Sans Microsoft YaHei SimHei Noto Sans CJK SC ...
找到支持中文的字体名称后,再进行配置即可。
也可以直接检查某个字体是否存在:
Python运行from matplotlib.font_manager import findfont print(findfont("Microsoft YaHei"))
如果返回一个字体文件路径,通常说明 Matplotlib 能够找到该字体。
五、使用 FontProperties 精确指定字体
全局设置适合整个程序都使用同一种中文字体。如果只希望某个标题或者图例使用中文字体,可以使用 FontProperties。
示例:
Python运行import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties font = FontProperties(fname="C:/Windows/Fonts/msyh.ttc") x = [1, 2, 3, 4, 5] y = [10, 25, 18, 32, 40] plt.plot(x, y) plt.title("销售数据趋势", fontproperties=font) plt.xlabel("月份", fontproperties=font) plt.ylabel("销售额", fontproperties=font) plt.show()
这种方法最大的优势是可以针对单个文本对象设置字体,不会影响整个 Matplotlib 环境。
如果字体文件路径明确,FontProperties 通常比单纯指定字体名称更加稳定。
六、解决图例中文显示问题
图例也是中文显示问题比较容易遗漏的位置。
例如:
Python运行import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] plt.rcParams["axes.unicode_minus"] = False x = [1, 2, 3, 4, 5] plt.plot(x, [10, 20, 15, 30, 40], label="实际销售额") plt.plot(x, [12, 18, 20, 28, 35], label="预计销售额") plt.title("销售额对比") plt.xlabel("月份") plt.ylabel("金额") plt.legend() plt.show()
只要全局字体设置正确,标题、坐标轴以及图例一般都会同时正常显示。
七、为什么中文正常了,但负号变成方框
这是 Matplotlib 中文字体配置中非常典型的另一个问题。
例如图表中存在负数:
Python运行y = [-10, -5, 0, 5, 10]
部分中文字体可能无法正确处理 Matplotlib 默认使用的 Unicode 负号,因此坐标轴上的负数可能出现异常。
解决方法就是:
Python运行plt.rcParams["axes.unicode_minus"] = False
完整示例:
Python运行import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] plt.rcParams["axes.unicode_minus"] = False x = [1, 2, 3, 4, 5] y = [-10, -5, 0, 5, 10] plt.plot(x, y) plt.title("温度变化趋势") plt.xlabel("日期") plt.ylabel("温度") plt.show()
因此,处理中文图表时,建议把中文字体和负号配置一起考虑。
八、服务器环境中的 Matplotlib 中文问题
本地 Windows 电脑能够正常显示中文,但代码部署到 Linux 服务器后出现方框,是非常常见的情况。
原因通常是:
本地安装了中文字体,而服务器没有安装。
例如代码:
Python运行plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
在 Windows 上可能正常,但服务器没有 Microsoft YaHei,自然无法找到对应字体。
对于 Linux 服务器,更适合准备一款开源中文字体,例如 Noto Sans CJK,然后指定字体文件。
示例:
Python运行from matplotlib.font_manager import FontProperties import matplotlib.pyplot as plt font = FontProperties( fname="/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc" ) plt.title("数据分析结果", fontproperties=font) plt.xlabel("时间", fontproperties=font) plt.ylabel("数值", fontproperties=font) plt.show()
实际路径需要根据服务器的字体安装位置调整。
九、程序中动态查找中文字体
如果代码需要同时运行在 Windows、macOS 和 Linux 上,不建议把某一个系统的字体路径写死。
可以准备多个候选字体,然后让程序自动选择。
例如:
Python运行import matplotlib.pyplot as plt from matplotlib.font_manager import fontManager font_names = {font.name for font in fontManager.ttflist} candidates = [ "Microsoft YaHei", "SimHei", "PingFang SC", "Noto Sans CJK SC", "WenQuanYi Zen Hei" ] for name in candidates: if name in font_names: plt.rcParams["font.sans-serif"] = [name] break plt.rcParams["axes.unicode_minus"] = False
这样可以减少程序对特定操作系统的依赖。
不过需要注意,字体名称必须与当前 Matplotlib 能识别的名称一致。
十、使用 Seaborn 时如何处理中文
如果项目同时使用 Seaborn 和 Matplotlib,也可以直接设置 Matplotlib 的全局参数。
Python运行import matplotlib.pyplot as plt import seaborn as sns plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] plt.rcParams["axes.unicode_minus"] = False sns.set_theme() sns.lineplot( x=[1, 2, 3, 4], y=[20, 35, 28, 45] ) plt.title("销售趋势") plt.xlabel("月份") plt.ylabel("销售额") plt.show()
如果发现 sns.set_theme() 等主题设置影响了字体,可以在主题设置完成后再次设置字体:
Python运行sns.set_theme() plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] plt.rcParams["axes.unicode_minus"] = False
这样更容易确保最终绘图配置符合预期。
十一、Matplotlib 找不到新安装的字体怎么办
有时候已经安装了字体,但 Matplotlib 仍然提示:
Glyph xxxx missing from current font
这可能是字体缓存没有及时更新。
可以先查看 Matplotlib 使用的缓存目录:
Python运行import matplotlib print(matplotlib.get_cachedir())
关闭 Python 程序后,可以删除对应的 Matplotlib 字体缓存,让下一次启动时重新扫描字体。
也可以在程序中查看当前字体管理器能够识别到的字体:
Python运行from matplotlib.font_manager import fontManager print(len(fontManager.ttflist))
如果新字体已经出现在 ttflist 中,说明字体扫描已经生效。
十二、图片保存后中文变成方框的处理方法
有些情况下,窗口中显示正常,但保存 PNG、JPG 或 PDF 后出现中文异常。
首先确保保存图片之前已经完成字体配置:
Python运行import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] plt.rcParams["axes.unicode_minus"] = False plt.plot([1, 2, 3], [10, 20, 15]) plt.title("销售数据") plt.savefig("result.png", dpi=300, bbox_inches="tight") plt.show()
对于需要提交报告、网页展示或打印的图片,可以适当提高 dpi,但清晰度与中文字体是否存在是两个不同的问题。
如果输出 PDF,还需要特别关注字体嵌入问题。某些字体格式或 PDF 后端的处理方式可能影响最终文件的兼容性,因此正式项目中最好使用实际环境验证生成结果。
十三、推荐封装成统一配置
如果一个项目中有大量绘图代码,每次都设置字体比较麻烦,可以单独封装配置函数。
Python运行import matplotlib.pyplot as plt from matplotlib.font_manager import fontManager def setup_matplotlib_chinese(): available_fonts = {font.name for font in fontManager.ttflist} candidates = [ "Microsoft YaHei", "SimHei", "PingFang SC", "Noto Sans CJK SC", "WenQuanYi Zen Hei" ] for font_name in candidates: if font_name in available_fonts: plt.rcParams["font.sans-serif"] = [font_name] break else: raise RuntimeError("当前系统没有找到可用的中文字体") plt.rcParams["axes.unicode_minus"] = False
程序启动时执行:
Python运行setup_matplotlib_chinese()
后续绘制图表时,就不需要反复配置。
这种方式尤其适合数据分析项目、报表系统以及自动生成图表的后端服务。
十四、排查 Matplotlib 中文乱码的思路
遇到中文显示异常时,可以按照以下顺序检查:
第一步,确认 Matplotlib 本身能够正常绘图。
第二步,查看系统是否安装中文字体。
第三步,通过 fontManager.ttflist 确认 Matplotlib 是否能够识别该字体。
第四步,使用字体名称设置:
Python运行plt.rcParams["font.sans-serif"] = ["字体名称"]
第五步,同时处理负号:
Python运行plt.rcParams["axes.unicode_minus"] = False
第六步,如果字体名称方式无效,直接使用字体文件路径:
Python运行FontProperties(fname="字体文件路径")
第七步,如果运行在服务器中,重点检查服务器是否真正安装了中文字体。
第八步,如果只是在导出的 PDF、图片中异常,则进一步检查保存格式和字体嵌入情况。
十五、一个完整的中文绘图示例
下面给出一个可以直接参考的完整示例:
Python运行import matplotlib.pyplot as plt # 设置中文字体 plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] # 解决负号显示问题 plt.rcParams["axes.unicode_minus"] = False months = ["一月", "二月", "三月", "四月", "五月", "六月"] sales = [120, 150, 135, 180, 210, 195] plt.figure(figsize=(9, 5)) plt.plot( months, sales, marker="o", label="销售额" ) plt.title("上半年销售数据趋势") plt.xlabel("月份") plt.ylabel("销售额(万元)") plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.savefig("sales.png", dpi=300, bbox_inches="tight") plt.show()
如果当前电脑安装了微软雅黑,这段代码中的标题、坐标轴、图例以及横坐标中文都可以正常显示。
十六、总结
Matplotlib 中文显示异常的根本原因通常是字体缺少中文字符或 Matplotlib 没有正确找到中文字体,而不是 Python 字符串本身存在编码问题。
最常用的解决方案是:
Python运行plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] plt.rcParams["axes.unicode_minus"] = False
如果代码需要跨平台运行,则应该根据 Windows、macOS 和 Linux 的实际字体情况选择合适字体。对于服务器、Docker 容器等无桌面环境,还需要确认系统中已经安装中文字体。
当字体名称配置不稳定时,可以进一步使用 FontProperties 直接指定字体文件。对于大型项目,则可以将中文字体配置统一封装,避免不同绘图模块重复处理。
掌握字体检查、全局配置、局部字体设置和服务器字体安装这几个关键环节后,大多数 Matplotlib 中文乱码、中文方框以及负号异常问题都能够快速定位和解决。