logging: local functions ==> loss of lineno

Peter Otten __peter__ at web.de
Thu Mar 11 06:14:08 EST 2010


Hellmut Weber wrote:

> Logging works very well giving the filename and line number of the point
> where it is called. As long as I use the loggers directly.
> BUT when I have to wrap the logger call in some other function, I always
> get file name and line number of the call of the logger inside the
> wrapping function.
> 
> Is there a possibility to get this information in this situation too?

The official way is probably to write a custom Logger class that overrides 
the findCaller() method.

Below is a hack that monkey-patches the logging._srcfile attribute to ignore 
user-specified modules in the call stack:

$ cat wrapper.py
import logging
import os
import sys

logger = logging.getLogger()

class SrcFile(object):
    def __init__(self, exclude_files):
        self.files = set(exclude_files)
    def __eq__(self, other):
        return other in self.files

def fixname(filename):
    if filename.lower().endswith((".pyc", ".pyo")):
        filename = filename[:-4] + ".py"
    return os.path.normcase(filename)

if "--monkey" in sys.argv:
    print "patching"
    logging._srcfile = SrcFile([logging._srcfile, fixname(__file__)])

def warn(*args, **kw):
    logger.warn(*args, **kw)

$ cat main.py
import logging
logging.basicConfig(format="%(filename)s <%(lineno)s>: %(message)s")
import wrapper
wrapper.warn("foo")
wrapper.warn("bar")
wrapper.warn("baz")

$ python main.py
wrapper.py <23>: foo
wrapper.py <23>: bar
wrapper.py <23>: baz

$ python main.py --monkey
patching
main.py <4>: foo
main.py <5>: bar
main.py <6>: baz

$ python -V
Python 2.6.4

Peter



More information about the Python-list mailing list