Linux下Matplotlib使用Times New Roman字体的解决方案

背景 :在Linux服务器上使用matplotlib或seaborn绘制论文图表时,经常会遇到findfont: Font family ['Times New Roman'] not found的错误。本文将介绍两种解决方案:系统级字体安装和代码级动态加载,帮助你在Linux环境下完美使用Times New Roman字体。

一、问题描述

在使用matplotlib或seaborn进行科研绘图时,为了符合论文格式要求,我们通常需要设置字体为Times New Roman。但在Linux系统(如Ubuntu、CentOS等)中,默认并未安装该字体,导致出现以下警告:

复制代码
findfont: Font family ['Times New Roman'] not found. Falling back to DejaVu Sans.

二、解决方案一:系统级字体安装

这是最彻底的解决方案,将Times New Roman字体安装到系统字体库中,所有应用程序均可使用。

步骤1:从Windows获取字体文件

Times New Roman字体受版权保护,最安全的获取方式是从已授权的Windows系统中复制:

  1. 在Windows系统中打开 C:\Windows\Fonts 文件夹
  2. 搜索 "Times New Roman"
  3. 复制以下四个字体文件到桌面:
    • times.ttf(常规)
    • timesbd.ttf(粗体)
    • timesbi.ttf(粗斜体)
    • timesi.ttf(斜体)

步骤2:上传到Linux服务器

将四个字体文件上传到Linux系统的字体目录(需要sudo权限):

bash 复制代码
# 创建字体存放目录(如果不存在)
sudo mkdir -p /usr/share/fonts/

# 上传字体文件(使用scp、rsync或FTP工具)
scp times*.ttf user@server:/usr/share/fonts/

或者上传到用户级目录(无需sudo):

bash 复制代码
mkdir -p ~/.local/share/fonts/
cp times*.ttf ~/.local/share/fonts/

步骤3:更新字体缓存

执行fc-cache命令刷新系统字体缓存:

bash 复制代码
# 系统级字体缓存更新
sudo fc-cache -fv /usr/share/fonts/

# 或用户级缓存更新
fc-cache -fv ~/.local/share/fonts/

参数说明

  • -f:强制重新生成缓存
  • -v:显示详细过程

验证字体是否安装成功:

bash 复制代码
fc-list | grep "Times New Roman"

预期输出:

复制代码
/usr/share/fonts/times/times.ttf: Times New Roman:style=Regular
/usr/share/fonts/times/timesbd.ttf: Times New Roman:style=Bold

步骤4:清除matplotlib缓存

这是关键步骤!matplotlib会缓存字体列表,必须清除才能识别新字体:

python 复制代码
import matplotlib
print(matplotlib.get_cachedir())  # 查看缓存路径
bash 复制代码
# 删除matplotlib字体缓存
rm -rf ~/.cache/matplotlib/

步骤5:在代码中使用

python 复制代码
import matplotlib.pyplot as plt

# 设置全局字体
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['font.size'] = 12

# 绘图测试
plt.figure(figsize=(8, 6))
plt.plot([1, 2, 3], [4, 5, 6], label='Sample Data')
plt.title('Title in Times New Roman')
plt.xlabel('X-axis Label')
plt.ylabel('Y-axis Label')
plt.legend()
plt.savefig('test_font.png', dpi=300, bbox_inches='tight')
plt.show()

三、解决方案二:代码级动态加载(临时方案)

如果你无法修改系统字体(如没有sudo权限,或在共享服务器上),可以使用fontManager.addfont()方法在代码中动态加载字体。

适用场景

  • 无系统管理员权限
  • 临时使用特定字体
  • 需要在不同环境中快速部署

具体实现

python 复制代码
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

# 动态添加字体(无需系统安装)
font_path = '/your_server_dirfonts/times.ttf'  # 字体文件路径
fm.fontManager.addfont(font_path)

# 创建字体属性对象
times_font = fm.FontProperties(fname=font_path)

# 验证字体加载
print(f"Loaded font: {times_font.get_name()}")

# 使用方式1:局部设置(推荐,灵活性高)
plt.figure(figsize=(8, 6))
plt.plot([1, 2, 3], [4, 5, 6])

# 对特定文本元素应用字体
plt.title('Title with Times New Roman', fontproperties=times_font, size=14)
plt.xlabel('X-axis', fontproperties=times_font, size=12)
plt.ylabel('Y-axis', fontproperties=times_font, size=12)

# 图例字体设置
plt.legend(['Data'], prop=times_font)

plt.tight_layout()
plt.savefig('dynamic_font.png', dpi=300)
plt.show()

进阶:批量添加多个字体样式

python 复制代码
import matplotlib.font_manager as fm
import os

# 定义字体目录
font_dir = '//your_server_dirfonts/times/'

# 自动添加目录下所有字体文件
for font_file in os.listdir(font_dir):
    if font_file.endswith(('.ttf', '.otf', '.ttc')):
        full_path = os.path.join(font_dir, font_file)
        fm.fontManager.addfont(full_path)
        print(f"Added: {font_file}")

# 设置全局默认字体
plt.rcParams['font.family'] = 'Times New Roman'

![动态加载效果截图占位符]
图4:动态加载字体后的渲染效果


五、常见问题与排查

Q1:执行fc-cache后仍找不到字体?

排查步骤

  1. 确认字体文件权限:chmod 644 /usr/share/fonts/truetype/times/*.ttf
  2. 检查字体格式是否为TTF/OTF
  3. 确认缓存清除彻底:rm -rf ~/.cache/matplotlib/*

Q2:中文显示为方框或乱码?

Times New Roman不支持中文字符,需要混合字体设置:

python 复制代码
# 英文用Times New Roman,中文用SimHei
plt.rcParams['font.family'] = ['Times New Roman', 'SimHei']
# 或分别指定
plt.xlabel('中文标签', fontproperties='SimHei')
plt.ylabel('English Label', fontproperties='Times New Roman')

Q3:Docker容器内字体失效?

在Dockerfile中添加:

dockerfile 复制代码
COPY times*.ttf /usr/share/fonts/truetype/times/
RUN fc-cache -fv && rm -rf /root/.cache/matplotlib/
相关推荐
飞yu流星2 小时前
文件压缩、文本内容、文本编辑
运维·服务器
洪流之源2 小时前
图像格式转换与内存对齐详解
linux
二宝哥2 小时前
Failed connect to mirrorlist.centos.org:80; Connection refused
linux·运维·centos
humors2212 小时前
一些安全类网站(不定期更新)
linux·网络·windows·安全·黑客·白帽
Kk.08023 小时前
Linux(九)fork复制进程与写时拷贝技术
linux·运维·服务器
一个人旅程~3 小时前
双系统时windows如何读取linux ext4格式硬盘分区?
linux·windows·经验分享·电脑
齐齐大魔王3 小时前
linux-进程详解
linux·运维·服务器
應呈3 小时前
Bootloader与OTA学习记录
linux·运维·服务器
勤自省3 小时前
在Ubuntu20.04上安装ROS
linux·ros