`warnings.warn` 的行为不一致

问题描述 投票:0回答:1

在 Google Colab 中,当我运行以下命令时:

def f():
    import warnings
    warnings.warn("deprecated", DeprecationWarning, stacklevel=2)

def g():
    return f()

def h():
    return g()

h() # or f() or g()

我在输出中收到 1 个警告:

<ipython-input-9-e09ca081f372>:6: DeprecationWarning: deprecated
  return f()

当我跑步时:

f()
g()
h()

我只收到 2 个警告(我预计会收到 3 个警告,因为所有 3 个函数都被调用了):

<ipython-input-10-0d5243608655>:1: DeprecationWarning: deprecated
  f()
<ipython-input-9-e09ca081f372>:6: DeprecationWarning: deprecated
  return f()

现在,我在 Python 终端中尝试了相同的操作,但只收到了

f()
g()
的警告,而不是
h()

的警告
Python 3.11.1 (main, Feb  5 2023, 16:11:00) [Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def f():
...     import warnings
...     warnings.warn("deprecated", DeprecationWarning, stacklevel=2)
... 
>>> def g():
...     return f()
... 
>>> def h():
...     return g()
... 
>>> f()
<stdin>:1: DeprecationWarning: deprecated
>>> g()
<stdin>:2: DeprecationWarning: deprecated
>>> h()
>>>

我想了解:

  1. 为什么当我单独运行
    h()
    时会在 colab 中看到警告,而当我在同一单元格中运行
    f()
    g()
    时却看不到警告?为什么
    h()
    从不在 Python 终端中显示警告(我认为这是因为
    stacklevel=2
    )?在 colab 中运行警告代码与在 Terminal Python 中运行警告代码究竟有何不同?
  2. 如何才能让我或某些包装函数每次调用
    f()
    时都显示警告消息?
  3. stacklevel
    skip_file_prefixes
    如何融入这一切?

谢谢你:)

python terminal google-colaboratory warnings stack-level
1个回答
0
投票

这是由于默认的警告过滤器,它只会打印每个位置第一次出现的警告。使用

stacklevel=2
时,警告位置是调用
f()
的位置,当您直接在笔记本中调用
<ipython-input-10-0d5243608655>:1
时,警告位置为
f()
;当您直接或间接调用
<ipython-input-9-e09ca081f372>:6
时,警告位置位于
g()
内部通过
g()
。相同的逻辑适用于终端会话。请注意,如果您在
h()
之前调用
h()
,则警告将在
g()
之后打印:
h()

笔记本和终端不一致大概就是这个问题:
https://github.com/ipython/ipython/issues/11207

如果您希望在每次调用时都打印警告,您可以通过运行

Python 3.12.3 (main, Apr 17 2024, 00:00:00) [GCC 13.2.1 20240316 (Red Hat 13.2.1-7)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> def f(): ... import warnings ... warnings.warn("deprecated", DeprecationWarning, stacklevel=2) ... >>> def g(): ... return f() ... >>> def h(): ... return g() ... >>> f() <stdin>:1: DeprecationWarning: deprecated >>> h() <stdin>:2: DeprecationWarning: deprecated >>> g() >>> g() >>> h() >>>

以编程方式更改警告过滤器。

    

© www.soinside.com 2019 - 2024. All rights reserved.