在Windows的Python3.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。我到处找遍了,但找不到解决这个问题的办法。
发布于 2020-01-03 20:23:32
matplotlib的绘图样式中的字体属性由FontManager类管理,并由FontProperties类指定。要获取这些字体属性,matplotlib内部使用FontManager类的一个实例调用一个findfont()函数,该函数搜索字体并返回符合FontProperties实例中字体规范的本地或系统字体路径中的最佳TrueType (TTF)字体文件。规范中的默认回退字体是DejaVu Sans。字体系列可以设置为以下参数之一:“serif”、“sans-serif”、“cursive”、“幻想”或“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设置为类似于sans-serif家族的'Lato‘字体。
在我更改FONTNAME之前,首先了解字体搜索是如何发生的,这一点很重要。现在,字体搜索是一项昂贵的任务,为了提高后续请求的效率,字体信息被缓存在一个JSON文件中。您可以在源代码中找到FontManager类的证据。对于Windows,此文件位于:%userprofile%.matplotlib。有关详细信息,请参阅FontManager类文档的Notes部分:
这执行最近的邻居搜索。每个字体都被赋予与目标字体属性相似的分数。返回得分最高的第一个字体。如果未找到低于某个阈值的匹配项,则返回默认字体(通常为DejaVu Sans)。 结果是缓存的,因此后续查找不必执行O(n)最近邻搜索。
在我的计算机(Windows 10)上,我有两个缓存文件:fontlist-V 300和fontlist-V 310。如果检查这些文件的内容,它将显示字体列表及其属性,如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()绘图(默认字体)

findfont()函数将始终查找缓存文件(如果缓存文件不存在,则创建缓存文件),如果我在计算机上安装了新字体,则重要的是更新该缓存文件,否则它将继续显示回退字体(与默认字体相同)。在继续下一步之前,请确保Lato字体为正确安装。字体应可在控制面板中的字体下使用。
现在正确安装了Lato字体,删除缓存文件并将sans-serif字体设置为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 serif字体)

您还将看到已经创建了一个新的缓存文件。上面的片段重新构建了缓存文件,该文件现在也有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'图

备注:所有步骤都是在IPython控制台上执行的,为了使更改生效,可能需要重新启动IPython会话。
发布于 2020-01-03 21:43:12
如果您想使用新安装的字体,那么不需要重新构建缓存,您必须按照@amanb的建议,首先使用 删除和更新 缓存,然后必须重新启动IPython会话/朱庇特笔记本/任何编程Python on的内容,然后matplotlib.rcParams才能识别您的新字体。
我给出的链接是Linux的说明,但想法是相同的-删除旧缓存,以便创建一个包含新字体的新缓存。对于Windows,只需在文件资源管理器中输入%userprofile%/.matplotlib,您就会看到类似于fontlist-v300.json的文件。那是字体缓存文件。您还可以在Python中运行matplotlib.get_cachedir()来查看缓存文件的路径。
你应该删除那个缓存文件。然后重新启动会话/记事本,然后运行
matplotlib.rcParams['font.family'] = 'sans-serif'
matplotlib.rcParams['font.sans-serif'] = [FONTNAME]看看你的新字体现在是否显示。(将创建一个新的缓存。)
由于Lato不是最近在这台(Linux) PC上安装的,所以运行以下代码(设置并找到字体)确实给出了正确的字体。因此,我很确定的问题在于您的字体缓存在安装新字体后没有被更新的。
import matplotlib as mpl
from matplotlib.font_manager import findfont, FontProperties
import matplotlib.pyplot as plt
x = [1, 2, 3]
y = [4, 5, 6]
mpl.rcParams['font.sans-serif'] = ['Lato'] # sets font to Lato
mpl.rcParams['font.weight'] = 'heavy' # otherwise can't see it lol
font = findfont(FontProperties(family=['sans-serif'])) # finds the font used
print(font)
plt.plot(x, y)
plt.title("Hello", size=45)
plt.show()
mpl.rcParams['font.sans-serif'] = ['DejaVu Sans']
mpl.rcParams['font.weight'] = 'normal'
font = findfont(FontProperties(family=['sans-serif']))
print(font)
plt.plot(x, y)
plt.title("Hello", size=45)
plt.show()

https://stackoverflow.com/questions/59391050
复制相似问题