在 WSL 里跑通了 Python 环境后,很多同学开始用 cartopy 和 matplotlib 画图了。结果一运行代码,满屏红字:findfont: Font family 'SimHei' not found.。
因为 WSL 的 Ubuntu 是一个精简系统,默认没有中文字体和 Arial。今天我们就来聊聊 Linux 下 Matplotlib 的字体配置,并教你如何解决这个问题。
系统字体目录:如 /usr/share/fonts/ 或 ~/.local/share/fonts/。
Matplotlib 自带目录:安装包里自带的几个基础字体。
缓存文件(重点):Matplotlib 会把扫描到的字体列表缓存成一个 JSON 文件(在 ~/.cache/matplotlib/ 下)。
报错的根源:当你在系统里新装了字体,Matplotlib 并不会立刻知道。它依然在读取旧的 JSON 缓存,自然就找不到新字体了。
既然我们在 WSL 里,Windows 系统自带了丰富的字体,直接“拿来主义”最省事。
在 WSL 终端执行以下命令,将需要的 Arial 和 SimHei(黑体)复制到 Linux 用户字体目录:
# 创建用户字体目录mkdir -p ~/.local/share/fonts# 复制 Arial (英文)cp /mnt/c/Windows/Fonts/arial*.ttf ~/.local/share/fonts/# 复制 SimHei (中文)cp /mnt/c/Windows/Fonts/simhei.ttf ~/.local/share/fonts/
也可以在终端执行下面的命令,安装其他字体
# 文泉驿微米黑(黑体风格,推荐替代 SimHei)sudo apt install fonts-wqy-microhei# 文泉驿正黑sudo apt install fonts-wqy-zenhei# 思源字体(Noto 系列,Google 出品,非常全)sudo apt install fonts-noto-cjk
告诉 Linux 系统:“我加了新字体了!”
Step 3:清除 Matplotlib 缓存(重要)
rm -rf ~/.cache/matplotlib/*
查看安装了哪些字体
from matplotlib import font_managerfonts = sorted(set(f.name for f in font_manager.fontManager.ttflist))print("可用字体数量:", len(fonts))print("可用字体列表:")for font in font_manager.fontManager.ttflist: print(font.name) # print(font.fname) # 获取字体文件路径
import matplotlib.pyplot as pltimport cartopy.crs as ccrsimport frykit.plot as fpltplt.rcParams['font.family']=['Times New Roman','Noto Sans CJK SC Medium']fig, ax = plt.subplots(figsize=(12,9),subplot_kw={'projection':ccrs.PlateCarree()})fplt.add_cn_border(ax)region = [70,140,15,55]ax.set_extent(region, crs=ccrs.PlateCarree())ax.coastlines()ax.stock_img()ax.gridlines(draw_labels=True)ax.set_title('中国地图')ax.text(0.5, -0.08, '经度', transform=ax.transAxes, ha='center', fontsize=14)ax.text(-0.06, 0.5, '纬度', transform=ax.transAxes, ha='center', va='center', rotation=90, fontsize=14)# plt.savefig('china.png',dpi=300)plt.show()
通过以上的案例可以看出,当前已经可以使用中文字体了,一下是 GLM 推荐的中文字体:
Noto Sans CJK SC ★★★★★Noto Serif CJK SC ★★★★★SimHei ★★★★☆SimSun-ExtB ★★★★☆WenQuanYi Zen Hei ★★★☆☆
如果你主要是 Matplotlib 制图,我建议优先使用 Noto Sans CJK SC;如果是论文插图、期刊图件,则优先考虑 Noto Serif CJK SC。