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?
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)