matplotlib mathtext字体警告:字体“default”没有字形

2024-09-28 13:22:58 发布

您现在位置:Python中文网/ 问答频道 /正文

当尝试运行为matplotlib.rcParams设置非默认值的脚本(在下面的最小工作示例中给出)时,我收到了maptplotlib警告:

$ python example.py
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.

这是在Ubuntu20.04上安装的TexLive2020,源代码可以找到matplotlib,Python 3.8.6使用pyenv从源代码构建

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.1 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
$ which latex
/usr/local/texlive/2020/bin/x86_64-linux/latex
$ $(pyenv which python) --version --version
Python 3.8.6 (default, Jan  5 2021, 00:14:15)
[GCC 9.3.0]

然而,当我尝试为一个最小的失败示例构建以下Docker映像时,我无法复制错误

最小工作/失败示例

对于以下Dockerfile

FROM ubuntu:20.04

RUN apt-get update -y && \
    apt-get install -y \
        fontconfig \
        fonts-dejavu \
        fonts-freefont-ttf \
        python3 \
        python3-dev \
        python3-pip \
        python3-venv \
        vim && \
        apt-get -y autoclean && \
        apt-get -y autoremove && \
        rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install --upgrade --no-cache-dir pip setuptools wheel && \
    python3 -m pip install --no-cache-dir "mplhep~=0.2.9" && \
    python3 -m pip list

WORKDIR /code

COPY example.py example.py

example.py

import numpy as np
import matplotlib.pyplot as plt
import mplhep


def make_plot(title=None):
    fig, ax = plt.subplots()
    x = np.linspace(0, 10, 101)
    y = np.square(x)
    ax.plot(x, y)
    ax.semilogy()

    ax.set_xlabel("$x$")
    ax.set_ylabel("$x^2$")
    if title is not None:
        ax.set_title(title)

    return fig, ax


def main():
    image_types = ["pdf", "png"]
    fig, ax = make_plot("Default matplotlib settings")

    for type in image_types:
        fig.savefig(f"default.{type}")

    mplhep.style.set_style("ATLAS")
    # above is equivalent to: plt.style.use(mplhep.style.ATLAS)
    fig, ax = make_plot("mplhep ATLAS style")
    for type in image_types:
        fig.savefig(f"ATLAS_style.{type}")


if __name__ == "__main__":
    main()

如果用

docker build . \
--pull \
-f Dockerfile \
-t matplotlib-font-question:debug-local

给予

$ docker run --rm -ti matplotlib-font-question:debug-local /bin/bash -c "pip list"
Package         Version
--------------- ---------
certifi         2020.12.5
chardet         4.0.0
cycler          0.10.0
idna            2.10
kiwisolver      1.3.1
matplotlib      3.3.3
mplhep          0.2.9
numpy           1.19.5
packaging       20.8
Pillow          8.1.0
pip             20.3.3
pyparsing       2.4.7
python-dateutil 2.8.1
requests        2.25.1
scipy           1.6.0
setuptools      51.1.1
six             1.15.0
urllib3         1.26.2
wheel           0.36.2

然后和我一起跑

docker run --rm --user 1000:1000 -v $PWD:$PWD -w $PWD matplotlib-font-question:debug-local /bin/bash -c "python3 /code/example.py"

与本地数据不同,生成的数据不会出现警告或错误

如果我检查Docker映像(没有LaTeX)上安装的字体库,这是令人困惑的

$ docker run --rm matplotlib-font-question:debug-local /bin/bash -c "apt list --installed | grep font"

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

fontconfig-config/now 2.13.1-2ubuntu3 all [installed,local]
fontconfig/now 2.13.1-2ubuntu3 amd64 [installed,local]
fonts-dejavu-core/now 2.37-1 all [installed,local]
fonts-dejavu-extra/now 2.37-1 all [installed,local]
fonts-dejavu/now 2.37-1 all [installed,local]
fonts-freefont-ttf/now 20120503-10 all [installed,local]
libfontconfig1/now 2.13.1-2ubuntu3 amd64 [installed,local]

在我的本地计算机上也可以找到所有找到的字体库

$ apt list --installed | grep font | grep "fontconfig\|dejavu"

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

fontconfig-config/focal,focal,now 2.13.1-2ubuntu3 all [installed,automatic]
fontconfig/focal,now 2.13.1-2ubuntu3 amd64 [installed,automatic]
fonts-dejavu-core/focal,focal,now 2.37-1 all [installed,automatic]
fonts-dejavu-extra/focal,focal,now 2.37-1 all [installed]
fonts-dejavu/focal,focal,now 2.37-1 all [installed]
libfontconfig1-dev/focal,now 2.13.1-2ubuntu3 amd64 [installed,automatic]
libfontconfig1/focal,now 2.13.1-2ubuntu3 amd64 [installed]

因此,我不清楚为什么当我安装了所有相同的字体和更多字体,并且它们还提供了关于matplotlib.rcParams的相同信息时,我会在本地收到警告:

码头工人

$ docker run --rm -ti matplotlib-font-question:debug-local
root@2e6cff635604:/code# python3
Python 3.8.5 (default, Jul 28 2020, 12:59:40)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>> import mplhep
>>> mplhep.style.set_style("ATLAS")
>>> for key, value in matplotlib.rcParams.items():
...     if "mathtext" in key:
...             print(key, value)
...
axes.formatter.use_mathtext False
mathtext.bf sans:bold
mathtext.cal cursive
mathtext.default rm
mathtext.fallback cm
mathtext.fallback_to_cm None
mathtext.fontset stixsans
mathtext.it sans:italic
mathtext.rm sans
mathtext.sf sans
mathtext.tt monospace
>>> for key, value in matplotlib.rcParams.items():
...     if "default" in key:
...             print(key, value)
...
mathtext.default rm

本地计算机

$ rm ~/.cache/matplotlib/fontlist-v330.json # not a cache issue
$ python
Python 3.8.6 (default, Jan  5 2021, 00:14:15)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>> import mplhep
>>> mplhep.style.set_style("ATLAS")
>>> for key, value in matplotlib.rcParams.items():
...     if "mathtext" in key:
...             print(key, value)
...
axes.formatter.use_mathtext False
mathtext.bf sans:bold
mathtext.cal cursive
mathtext.default rm
mathtext.fallback cm
mathtext.fallback_to_cm None
mathtext.fontset stixsans
mathtext.it sans:italic
mathtext.rm sans
mathtext.sf sans
mathtext.tt monospace
>>> for key, value in matplotlib.rcParams.items():
...     if "default" in key:
...             print(key, value)
...
mathtext.default rm

问题

为什么我的本地机器和Docker容器的结果不同? 在调试字体问题时,就我所知,一般来说,我将如何调试它

相关GitHub问题

我以前在Ubuntu19.10上遇到过这个问题(在下面链接的问题中有描述),但事情从那时起就神奇地开始工作了,我不知道如何或为什么,因为我在那里使用的方法在这里不起作用


Tags: installedkeyrmindefaultformatplotlibstyle
1条回答
网友
1楼 · 发布于 2024-09-28 13:22:58

最终,修复比just the font list cache更微妙。我在matplotlib缓存中的不仅仅是fontlist-v330.json

$ ls -htra ~/.cache/matplotlib/
..  tex.cache  fontlist-v330.json  .

因此,使用

import matplotlib.font_manager
matplotlib.font_manager._rebuild()

rm ~/.cache/matplotlib/fontlist-v330.json

这还不够。相反the entire ^{} cache needs to be updated,这是最容易用

rm ~/.cache/matplotlib/*

Why do the results differ between my local machine and the Docker container?

由于Docker映像没有以前的历史记录,它从一开始就没有缓存,因此没有什么可以把它搞砸的

How would I go about attempting to debug this in general, as this is about as far as I know how to get when debugging font issues?

我现在要确保在尝试做任何其他事情之前,我完全清理并移除我的缓存

相关问题 更多 >

    热门问题