Search code examples
pythonwarnings

How to reference the correct file when printing a warning in python?


I just started to use the warnings module in python. I'm trying to understand how to reference the correct line in a given file when I issue a warning.

I'm writing a module where some functions can issue warnings, but I would like all warnings to point to the line where they are issued in scripts where the module was imported, rather than to a line where they are issued in the module itself. I think I get how the stacklevel argument of warnings.warn works, but I don't see how to use it with functions of my module that are also used internally, since their stack level might vary.

I will try to make myself clear using an example. Say I write the following module, that I call testmodule.py.

import warnings

def f():
    warnings.warn('This is a test warning.', stacklevel=2)

def g():
    f()

Then I write the following script.

import testmodule as test

test.f()
test.g()

If I run this script, the output is

"script_filename":3: UserWarning: This is a test warning.
  test.f()
"module_filename":7: UserWarning: This is a test warning.
  f()

where "script_filename" and "module_filename" are the actual names of the files where I saved the script and the module on my computer.

In the above example, both warnings correctly identify the line where f is called. However, the warning issued when calling test.g points inside of testmodule, so it is not useful to a user of the module. Is there a way to make both of these warnings point to the line where they are issued in the script, and not in the module itself?


Solution

  • With these small changes, I got the exact behaviour you are asking for. Adding arguments to g() may not be what you wanted, but I think this is an answer, and may help you understand.

    import warnings
    
    def f(slevel=2):
        warnings.warn('This is a test warning.', stacklevel=slevel)
    
    def g(i):
        f(i)
    
    import testmodule  as test
    
    test.f()
    test.g(3)
    

    Outputs

    script_filename:3: UserWarning: This is a test warning.
      test.f()
    script_filename:4: UserWarning: This is a test warning.
      test.g(3)