Matplotlib无法找到已安装在我的Linux机器上的字体

23
我正在尝试在Python 3下使用matplotlib(版本1.4.2)绘制类似xkcd的图形。
当我运行以下命令时:
import matplotlib.pyplot as plt
plt.xkcd()
plt.plot([1,2,3,4], [1,4,9,16], 'bo')
plt.axis([0, 6, 0, 20])
plt.show()

它打开了一个没有任何图像的空窗口,我收到了错误提示:

/usr/lib/python3/dist-packages/matplotlib/font_manager.py:1279: UserWarning: findfont: Font family ['Humor Sans', 'Comic Sans MS', 'StayPuft'] not found. Falling back to Bitstream Vera Sans
  (prop.get_family(), self.defaultFamily[fontext]))
/usr/lib/python3/dist-packages/matplotlib/font_manager.py:1289: UserWarning: findfont: Could not match :family=Bitstream Vera Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=medium. Returning /usr/share/matplotlib/mpl-data/fonts/ttf/STIXSizOneSymReg.ttf
  UserWarning) Exception in Tkinter callback

我已经安装了Humor Sans字体,并用fc-list | grep Humor检查了它。它也可以在其他程序中使用,比如Libre Office。我还安装了staypuft。这不够吗?

相同的代码,但没有plt.xkcd()部分,可以完美地工作。

plt.show()的替代方法,如pylab.savefig()也无法与xkcd代码一起使用,但不会对不使用xkcd的相同代码造成任何问题。

5个回答

23
如果您在安装了matplotlib后添加了新字体,那么请尝试删除字体缓存。这样matplotlib将不得不重新构建缓存,从而添加新字体。该缓存可能位于~/.matplotlib/fontList.cache~/.cache/matplotlib/fontList.json

5
我搜索了 fontList 并在 ~/.cache/matplotlib/fontList.py3k.cache 找到了它。删除它可以让上述代码再次正常工作。 - Pierre B
2
是的,matplotlib配置文件的位置由操作系统定义。 - Serenity
在Windows中,您需要查看%HOMEPATH%.matplotlib。有一个名为fontList.py3k.cache的文件。删除它。如果您正在使用jupyter笔记本,则必须在新字体被选中并且缓存重新创建之前重新启动jupyter。 - Tom Johnson
7
您可以通过运行 import matplotlib as mpl; print(mpl.get_cachedir()) 来查找缓存目录的路径。 - steven

12

我在WSL2下使用apt-get安装了Ubuntu字体,但是它们不能被matplotlib使用。

在JupyterLab中使用matplotlib版本3.4.2,在安装新字体后,我需要执行以下步骤才能使其可用。

首先,删除matplotlib缓存目录:

import shutil
import matplotlib

shutil.rmtree(matplotlib.get_cachedir())

缓存位置可能因您的安装而异。以上代码保证您将删除适用于您的内核的正确缓存。

现在重新启动您的笔记本内核。

然后,在笔记本单元格中使用以下命令测试新字体是否出现:

import matplotlib.font_manager
from IPython.core.display import HTML

def make_html(fontname):
    return "<p>{font}: <span style='font-family:{font}; font-size: 24px;'>{font}</p>".format(font=fontname)

code = "\n".join([make_html(font) for font in sorted(set([f.name for f in matplotlib.font_manager.fontManager.ttflist]))])

HTML("<div style='column-count: 2;'>{}</div>".format(code))

上面的代码将显示Matplotlib中所有可用字体。


1
这很棒。在找到最终可行的方法之前,我花了将近一两个小时遇到了一些麻烦。 - Snehangsu

9

对于Mac用户:尝试在Python中运行以下命令(或在.py文件之前)。

import matplotlib

matplotlib.font_manager._rebuild()

这似乎是当前版本的matplotlib的工作解决方案。我找不到“fontList”缓存。 - ababuji
3
在至少 matplotlib v3.3.2 中,matplotlib.font_manager 在导入 matplotlib 时并不知道,因此您需要执行以下操作:matplotlib.font_manager._rebuild() - Matthew Feickert
19
在Matplotlib 3.4.2中,字体管理器没有“_rebuild”属性。我也找不到字体缓存。 - neves

7

正如 @neves 所指出的那样, matplotlib.font_manager._rebuild() 已经不能使用了。在手动删除缓存目录的替代方案中,适用于 Matplotlib 3.4.3 的是:

import matplotlib.font_manager
matplotlib.font_manager._load_fontmanager(try_read_cache=False)

这是用于该函数的 Matplotlib 源代码:
def _load_fontmanager(*, try_read_cache=True):
    fm_path = Path(
        mpl.get_cachedir(), f"fontlist-v{FontManager.__version__}.json")
    if try_read_cache:
        try:
            fm = json_load(fm_path)
        except Exception as exc:
            pass
        else:
            if getattr(fm, "_version", object()) == FontManager.__version__:
                _log.debug("Using fontManager instance from %s", fm_path)
                return fm
    fm = FontManager()
    json_dump(fm, fm_path)
    _log.info("generated new fontManager")
    return fm

3

如果有人想要为他们的图表选择自定义字体,可以手动设置图表标签、标题、图例或刻度标签的字体。以下代码演示了如何为您的图表设置自定义字体。这样可以消除您提到的错误。

import matplotlib.font_manager as fm
import matplotlib.pyplot as plt

font_path = '/System/Library/Fonts/PingFang.ttc'  # the location of the font file
my_font = fm.FontProperties(fname=font_path)  # get the font based on the font_path

fig, ax = plt.subplots()

ax.bar(x, y, color='green')
ax.set_xlabel(u'Some text', fontproperties=my_font)
ax.set_ylabel(u'Some text', fontproperties=my_font)
ax.set_title(u'title', fontproperties=my_font)
for label in ax.get_xticklabels():
    label.set_fontproperties(my_font)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接