python - 无法在 matplotlib 中使用自定义字体

标签 python python-3.x matplotlib fonts

我在获取自定义字体以在 Windows 上的 Python 3.7.3 上使用 Matplotlib(版本 3.1.1)时遇到问题。标准使用方式

import matplotlib as mpl
mpl.rcParams['font.family'] = 'sans-serif'
mpl.rcParams['font.sans-serif'] = [FONTNAME] 

适用于系统预装的一系列字体。我最近手动安装了 Lato 系列字体。但是,当我使用“Lato”作为 FONTNAME 时,Matplotlib 默认返回 Deja Vu Sans,甚至不会抛出任何错误。我还使用

重建了字体缓存
mpl.font_manager._rebuild()

当我运行时,现在会出现几种名为“Lato”的字体

mpl.font_manager.fontManager.ttflist

比如

 <Font 'Lato' (Lato-Semibold.ttf) normal normal semibold normal>,
 <Font 'Lato' (Lato-Thin.ttf) normal normal 400 normal>,
...

然而,这些情节看起来仍然像是使用 Deja Vu Sans。我找遍了所有地方,但找不到解决此问题的方法。

最佳答案

matplotlib 绘图样式中的字体属性由 FontManager 管理类并用 FontProperties 指定类(class)。 为了获取这些字体属性,matplotlib 在内部使用 FontManager 类的实例调用 findfont() 函数来搜索字体并返回本地或系统字体路径中最好的 TrueType (TTF) 字体文件匹配 FontProperties 实例中的字体规范。规范中的默认后备字体是 DejaVu Sans。字体系列可以设置为以下任一参数:“serif”、“sans-serif”、“cursive”、“fantasy”或“monospace”。可以像这样找到任何字体系列的 TTF 文件位置:

In [1]: from matplotlib.font_manager import findfont, FontProperties

In [2]: font = findfont(FontProperties(family=['sans-serif']))

In [3]: font
Out[3]: 'C:\\Users\\xxxxxx\\Anaconda3\\envs\\py3.7.4\\lib\\site-packages\\matplotlib\\mpl-data\\fonts\\ttf\\DejaVuSans.ttf'

“等宽”系列的另一个示例:

In [7]: font = findfont(FontProperties(family=['monospace']))

In [8]: font
Out[8]: 'C:\\Users\\xxxxxx\\Anaconda3\\envs\\py3.7.4\\lib\\site-packages\\matplotlib\\mpl-data\\fonts\\ttf\\DejaVuSansMono.ttf'

如您所见,上面的 sans-serif 系列指向默认的 DejaVuSans TTF 文件,因为我还没有将 FONTNAME 设置为其他字体,例如也属于的“Lato”字体无衬线字体系列。

在我更改FONTNAME 之前,首先了解字体搜索是如何发生的很重要。 现在字体搜索是一项昂贵的任务,为了使后续请求更高效,字体信息缓存在 JSON 文件中。您可以在 source code 中找到证据对于 FontManager 类。对于 Windows,此文件位于:%userprofile%\.matplotlib。有关详细信息,请参阅 FontManager 类文档的注释部分:

This performs a nearest neighbor search. Each font is given a similarity score to the target font properties. The first font with the highest score is returned. If no matches below a certain threshold are found, the default font (usually DejaVu Sans) is returned.

The result is cached, so subsequent lookups don't have to perform the O(n) nearest neighbor search.

在我的电脑 (Windows 10) 上,我有两个缓存文件:fontlist-v300fontlist-v310。如果您检查这些文件中的任何一个的内容,它会显示一个字体列表及其属性,例如 TTF 文件位置、样式、粗细等。观察默认系列键:

"defaultFamily": {
    "ttf": "DejaVu Sans",
    "afm": "Helvetica"
  }

至此,我们了解到该字体将以 DejaVu Sans 显示。这在情节的标题中最为明显:

In [1]: import matplotlib as mpl
   ...: mpl.rcParams['font.family'] = 'sans-serif'
   ...: import matplotlib.pyplot as plt
   ...: plt.plot(range(0,50,10))
   ...: plt.title('Font test', size=32)
   ...: plt.show()

绘图(默认字体):

default font fallback

findfont() 函数将始终查找缓存文件(如果不存在则创建一个),如果我在我的计算机上安装了新字体,那么这个缓存很重要文件已更新,否则它将继续显示后备字体(与默认字体相同)。在继续下一步之前,确保 Lato 字体是 installed correctly .该字体应该在控制面板的字体下可用。

现在正确安装了 Lato 字体,删除缓存文件并将无衬线字体设置为 Lato:

In [4]: import matplotlib as mpl^M
   ...: mpl.rcParams['font.family'] = 'sans-serif'
   ...: mpl.rcParams['font.sans-serif'] = 'Lato'
   ...: import matplotlib.pyplot as plt
   ...: plt.plot(range(0,50,10))
   ...: plt.title('Font test', size=32)
   ...: plt.show()

绘图(Lato sans-serif 字体):

enter image description here

您还将观察到一个新的缓存文件已创建。上面的代码片段重建了缓存文件,现在也有 Lato 字体的信息。同样,您可以在文本编辑器中打开此缓存文件以验证其存在。现在让我们验证 sans-serif 系列的 TTF 文件路径:

In [4]: from matplotlib.font_manager import findfont, FontProperties

In [5]: font = findfont(FontProperties(family=['sans-serif']))

In [6]: font
Out[6]: 'C:\\Users\\xxxxx\\AppData\\Local\\Microsoft\\Windows\\Fonts\\Lato-Thin.ttf'

如您所见,sans-serif 系列现在指向 Lato-Thin TTF 文件。

将字体样式更改为斜体也需要先删除缓存文件:

In [3]: In [4]: import matplotlib as mpl
   ...:    ...: mpl.rcParams['font.family'] = 'sans-serif'
   ...:    ...: mpl.rcParams['font.sans-serif'] = 'Lato'
   ...:    ...: mpl.rcParams['font.style'] = 'italic'
   ...:    ...: import matplotlib.pyplot as plt
   ...:    ...: plt.plot(range(0,50,10))
   ...:    ...: plt.title('Font test', size=32)
   ...:    ...: plt.show()

In [4]: from matplotlib.font_manager import findfont, FontProperties

In [5]: font = findfont(FontProperties(family=['sans-serif']))

In [6]: font
Out[6]: 'C:\\Users\\xxxxxx\\AppData\\Local\\Microsoft\\Windows\\Fonts\\Lato-HairlineItalic.ttf'

情节:

enter image description here

注意:所有步骤均在 IPython 控制台上执行,可能需要重新启动 IPython session 才能使更改生效。

关于python - 无法在 matplotlib 中使用自定义字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59391050/

相关文章:

python - 如何捕获 OpenCV 写入 stderr 的消息?

python-3.x - 展平 Pandas DataFrame 中的元素列表

python - matplotlib 中的 ax.fill() 填充错误区域

使用 FFMpegwriter 的 Python Matplotlib basemap 动画在 820 帧后停止?

python - 在群图之上绘制误差线

python - 我如何在整个 Penn Treebank 语料库上训练 NLTK?

python - 如何比较目录以确定哪些文件已更改?

python - 通过在 PyCharm 2016.3.2 中运行的 Python 3.6 脚本打开 UTF-8 编码的文件

python - 值错误: need more than 1 value to unpack

python - 如何使用 python 3.6 venv 创建 virtualenv