在 IPython 中抑制 Matplotlib 图例警告

Suppress Matplotlib Legend Warning in IPython

我正在创建一个包含大量数据的图表并为其添加图例:

import matplotlib.pyplot as plt
import numpy as np

plt.plot(np.arange(100000), np.random.random((100000, 10)), label='data')
plt.legend()

当图例实际在另一个线程中绘制时,这会生成警告(如预期):

<matplotlib.legend.Legend at 0x1b5824d04c8>C:\Users\...\lib\site-packages\ipykernel\eventloops.py:106: UserWarning: Creating legend with loc="best" can be slow with large amounts of data.
  app.exec_()

我想抑制这个特定的警告,所以我这样做了

from warnings import filterwarnings
filterwarnings("ignore", category=UserWarning, module="matplotlib")

运行 相同的绘图代码再次产生相同的警告。

如何抑制它?理想情况下,我想在对 legend 的调用周围使用 warnings.catch_warnings。像

with warnings.catch_warnings():
    plt.legend()

原始命令是 运行 在 spyder (ipython) 中使用 Qt5agg 后端的交互模式。我也在 运行 相同的命令后跟 plt.show() 在一个普通的 python 控制台中:

__main__:1: UserWarning: Creating legend with loc="best" can be slow with large amounts of data.

运行 filterwarnings("ignore", category=UserWarning, module="__main__") 有帮助,但仅限于非交互模式。在交互模式下, 发出以下警告:

C:\Users\...\lib\site-packages\pyreadline\console\console.py:514: UserWarning: Creating legend with loc="best" can be slow with large amounts of data.
  call_function(inputHookFunc, ())

这个问题似乎是 ipython 具体的。我正在使用

Python 3.8.3,IPython 7.16.1,matplotlib 3.2.2(和 numpy 1.18.5)

此答案显示了如何根据 OP 标题抑制图例警告。它没有解释如何在发出警告后暂时捕获警告。如果您对后者感兴趣,那么以下内容更像是一种解决方法而不是答案。

根据 source code,如果使用默认位置(来自 rcParams['legend.loc'],默认情况下为 'best'),则会显示警告,并且需要超过 1 秒才能找到最好的位置。如果您将位置明确设置为 'best',则不会发出警告。

在 Windows 上测试,IPython 和普通命令行(我不得不增加我机器上的数字):

import matplotlib.pyplot as plt
import numpy as np

np.random.seed(1)
plt.plot(np.arange(1_000_000), np.random.random((1_000_000, 10)), label='data')
plt.legend(loc='best')
plt.show()

作为替代方案,您可以通过其消息(而不是模块)永久抑制警告:

filterwarnings("ignore", 'Creating legend with loc="best" can be slow with large amounts of data.')

缺点是它是永久性的。我找不到通过使用上下文管理暂时抑制警告的方法,因为上下文当然在图例位置计算发生之前很久就关闭了。
要将此更改恢复到警告过滤器列表,您可以在 最终绘制图例后 执行以下操作之一:warnings.filters = [w for w in warnings.filters if not w[1] or not re.match(w[1], 'Creating legend with loc="best" can be slow with large amounts of data.')]filterwarnings("default", 'Creating legend with loc="best" can be slow with large amounts of data.').