问题描述
在使用 Python 的 Matplotlib 库绘图时,当需要显示中文字符(如标题、标签或图例)时,经常会遇到以下警告:
UserWarning: findfont: Font family 'SimHei' not found.
即使已经正确安装了中文字体,这个警告仍可能出现,导致图表中的中文显示为方框或乱码。本文将详细介绍这个问题的原因和解决方法。
问题原因
这个问题通常有以下几个原因:
- 字体未安装:系统中没有安装 ‘SimHei’(黑体)等中文字体。
- 字体已安装但 Matplotlib 无法识别:这是最常见的情况,即使使用
fc-list
命令可以看到字体已安装,但 Matplotlib 的字体缓存没有正确更新。 - 字体路径配置不正确:Matplotlib 的字体搜索路径没有包含自定义字体目录。
解决方案
方案一:安装中文字体
首先,确保系统中已安装中文字体。
Ubuntu/Debian 系统:
sudo apt-get update
sudo apt-get install -y fonts-wqy-microhei fonts-wqy-zenhei xfonts-wqy
CentOS/RHEL 系统:
sudo yum install -y wqy-microhei-fonts wqy-zenhei-fonts
方案二:手动添加中文字体
如果需要特定的中文字体(如 SimHei),可以手动添加:
- 创建用户字体目录:
mkdir -p ~/.fonts
- 将字体文件复制到该目录:
# 假设您已经有 SimHei.ttf 文件
cp SimHei.ttf ~/.fonts/
# 或者为了明确区分
cp SimHei.ttf ~/.fonts/chinese.simhei.ttf
- 刷新字体缓存:
fc-cache -fv
- 验证字体安装成功:
fc-list | grep -i simhei
如果成功,将显示类似以下的输出:
/home/user/.fonts/SimHei.ttf: 黑体,SimHei:style=Regular
方案三:清除 Matplotlib 字体缓存(关键步骤)
即使字体已正确安装,Matplotlib 仍可能无法识别它,这是最常见的问题。解决方法是清除 Matplotlib 的字体缓存:
rm -rf ~/.cache/matplotlib
这将强制 Matplotlib 在下次使用时重新扫描系统字体。
方案四:在代码中正确设置字体
在 Python 代码中,可以通过以下方式设置中文字体:
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
# 方法一:直接设置字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
# 方法二:使用 FontProperties
font = FontProperties(fname='/path/to/SimHei.ttf', size=14)
plt.title('中文标题', fontproperties=font)
方案五:编写健壮的字体选择函数
为了增强代码的健壮性,可以实现一个函数来尝试多种中文字体:
from matplotlib.font_manager import FontProperties
def get_font_properties():
"""获取可用的字体属性,尝试依次使用中文字体"""
# 尝试多种中文字体,按优先级排序
font_names = ['SimHei', 'Microsoft YaHei', 'SimSun', 'NSimSun', 'FangSong', 'KaiTi', 'Arial Unicode MS']
# 创建临时字体属性来测试
font_prop = FontProperties()
# 尝试设置每种字体,直到找到系统上可用的字体
for font_name in font_names:
try:
font_prop.set_family(font_name)
print(f"使用字体: {font_name}")
return font_prop
except:
continue
# 如果以上都失败,使用默认字体
print("未找到合适的中文字体,将使用系统默认字体")
return None
# 使用字体
font_prop = get_font_properties()
if font_prop:
plt.rcParams['font.family'] = font_prop.get_family()
实际案例:解决 SimHei 字体警告
我们曾在一个项目中遇到了类似问题,尽管已经安装了 SimHei 字体并且 fc-list
能够找到它,但 Matplotlib 仍然报出警告。
问题诊断
- 首先确认字体是否已安装:
fc-list | grep -i simhei
输出:
/home/user/.fonts/chinese.simhei.ttf: 黑体,SimHei:style=Regular
/home/user/.fonts/SimHei.ttf: 黑体,SimHei:style=Regular
- 检查 Matplotlib 是否能识别这些字体:
python -c "import matplotlib.font_manager as fm; print([f.name for f in fm.fontManager.ttflist if 'simhei' in f.name.lower()])"
初始输出为空列表 []
,表明 Matplotlib 无法识别这些字体。
解决步骤
- 清除 Matplotlib 的字体缓存:
rm -rf ~/.cache/matplotlib
- 再次检查 Matplotlib 能否识别字体:
python -c "import matplotlib.font_manager as fm; print([f.name for f in fm.fontManager.ttflist if 'simhei' in f.name.lower()])"
现在输出为 ['SimHei', 'SimHei']
,表明 Matplotlib 已成功识别字体。
- 运行绘图脚本,确认不再出现警告,且中文显示正常。
常见问题与解决方法
-
问题:清除缓存后仍然无法识别字体
解决:检查字体文件是否损坏,尝试重新下载或使用其他中文字体。 -
问题:部分字符显示为方框
解决:确保选择的字体包含所需的所有字符集。 -
问题:在容器或虚拟环境中运行时字体问题
解决:需要在容器中安装字体,或将字体文件挂载到容器中。
总结
解决 Matplotlib 中文字体显示问题的关键步骤是:
- 确保系统安装了所需的中文字体
- 清除 Matplotlib 的字体缓存(通常这是最关键的步骤)
- 在代码中正确设置字体
通过以上步骤,可以解决大多数 Matplotlib 中文显示问题,使图表正常显示中文字符。