cpython icon indicating copy to clipboard operation
cpython copied to clipboard

`warnings.simplefilter("once")` and `warnings.warn()` print all occurrences of matching warnings, regardless of location

Open hyperkai opened this issue 1 year ago • 2 comments

Bug report

Bug description:

With warnings.simplefilter("module") and warnings.warn(), I ran main.py which runs file1.py(module) and file2.py(module) as shown below:

*Memos:

  • The doc says "module" print the first occurrence of matching warnings for each module where the warning is issued (regardless of line number).
  • I also used warnings.filterwarnings("module").
  • I ran it on Windows and Linux.
my_project
 |-main.py
 |-file1.py(module)
 └-file2.py(module)

main.py:

import warnings
warnings.simplefilter("module")

import file1, file2

file1.py:

import warnings

warnings.warn("Warning 1")
warnings.warn("Warning 2")
warnings.warn("Warning 3")

file2.py:

import warnings

warnings.warn("Warning 1")
warnings.warn("Warning 2")
warnings.warn("Warning 3")

Then, "module" print the first occurrence of matching warnings for each module where the warning is issued (regardless of line number)` as shown below:

...\my_project\file1.py:3: UserWarning: Warning 1
  warnings.warn("Warning 1")
...\my_project\file1.py:4: UserWarning: Warning 2
  warnings.warn("Warning 2")
...\my_project\file1.py:6: UserWarning: Warning 3
  warnings.warn("Warning 3")
...\my_project\file2.py:3: UserWarning: Warning 1
  warnings.warn("Warning 1")
...\my_project\file2.py:4: UserWarning: Warning 2
  warnings.warn("Warning 2")
...\my_project\file2.py:6: UserWarning: Warning 3
  warnings.warn("Warning 3")

Now with warnings.simplefilter("once") and warnings.warn(), I ran main.py which runs file1.py(module) and file2.py(module) as shown below:

*Memos:

  • The doc says "once" print only the first occurrence of matching warnings, regardless of location.
  • I also used warnings.filterwarnings("once").
  • I ran it on Windows and Linux.
import warnings
warnings.simplefilter("once")

import file1, file2

But "once" print all occurrences of matching warnings, regardless of location as shown below:

...\my_project\file1.py:3: UserWarning: Warning 1
  warnings.warn("Warning 1")
...\my_project\file1.py:4: UserWarning: Warning 2
  warnings.warn("Warning 2")
...\my_project\file1.py:6: UserWarning: Warning 3
  warnings.warn("Warning 3")
...\my_project\file2.py:3: UserWarning: Warning 1
  warnings.warn("Warning 1")
...\my_project\file2.py:4: UserWarning: Warning 2
  warnings.warn("Warning 2")
...\my_project\file2.py:6: UserWarning: Warning 3
  warnings.warn("Warning 3")

CPython versions tested on:

3.11

Operating systems tested on:

Linux, Windows

hyperkai avatar Oct 20 '24 21:10 hyperkai

I can confirm this behaviour. But this seems weird that no one has ever noticed it so I'm wondering whether there is something I'm misunderstanding.

cc @ncoghlan

picnixz avatar Oct 22 '24 15:10 picnixz

There's a docs ambiguity here, since it doesn't explicitly state how the three filters that suppress repeated warnings determine if a warning is a repeat:

  • default: only full (message, category, module, lineno) matches are considered repeats
  • module: any warnings that match on (message, category, module) are considered repeats
  • once: any warnings that match on (message, category) are considered repeats

Unlike the initial check against the filter definition, these definitions are not affected by which fields are defined in the filter string. This is why a filter like default::DeprecationWarning works the way it does: the given action is applied to every reported deprecation warning, but they're not all considered to be the same deprecation warning.

error, always, ignore aren't affected by the ambiguity since they don't check for repeats in the first place

So in the example, all 6 warnings are considered distinct, since they all have different messages. If you drop the distinguishing numbers from each of them, you'll see once and module behaving as you expect.

That's a genuine flaw in the docs, but the behaviour is as expected, so I'll adjust the labels accordingly.

ncoghlan avatar Oct 23 '24 14:10 ncoghlan

I will take a look! @corona10

byungchanKo99 avatar Nov 02 '24 08:11 byungchanKo99

Thanks for the docs update @byungchanKo99! The main PR has been merged, and the backport PRs will automatically merge once their CI runs complete.

It may be a while before the change goes lives on docs.python.org, though (almost always within 24 hours, but most often faster than that - building the full docs set with all its translations can take a while)

ncoghlan avatar Nov 02 '24 11:11 ncoghlan

Closing since completed and backported. Thank you all!

picnixz avatar Nov 02 '24 11:11 picnixz