Very often when writing framework code, I would prefer the caller's line number and file name to be logged. For example, if I detect improper use of a framerwork level API call, I would like to log that.... not as an in-framework error but as "caller error".
This only comes into play when writing low level libraries and systems that use introspectionn.
Is there any way to get the logger to log "one level up"? Can I create a custom LogRecord and then modify it and use it within the installed loggers somehow? Trying to figure this out.
For example something like this:
def set(self, x):
if x not in self._cols:
log.error("Invalid attribute for set", stack_level=-1)
This is easy to find on google now since it was added to python 3.8, and it was mentioned in the other answer but here is a better explanation. You were close with the stack_level
argument, but it should be stacklevel
and the value should be 2
. For example you can do:
import logging
def fun():
logging.basicConfig(format='line %(lineno)s : %(message)s')
log = logging.getLogger(__name__)
log.error('Something is wrong', stacklevel=2)
if __name__ == '__main__':
fun()
This will output:
line 9 : Something is wrong
If the stacklevel was set to the default of 1
, it would output:
line 6 : Something is wrong
From the documentation: https://docs.python.org/3/library/logging.html#logging.Logger.debug
The third optional keyword argument is stacklevel, which defaults to 1. If greater than 1, the corresponding number of stack frames are skipped when computing the line number and function name set in the LogRecord created for the logging event. This can be used in logging helpers so that the function name, filename and line number recorded are not the information for the helper function/method, but rather its caller. The name of this parameter mirrors the equivalent one in the warnings module.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With