logging: local functions ==> loss of lineno

Peter Otten __peter__ at web.de
Wed Mar 31 09:52:09 CEST 2010

Hellmut Weber wrote:

> Hi Peter and Jean-Michel,
> thanks for all your hints and pieces of code.
> It took me a while to play around with what I got from you (and some
> study of Vinay's module documentation.
> Now I have come up with a more complete solution I'm quite satisfied
> with. And I would be very glad to receive your comments on my code
> indicating what I could do better, given that I'm still at the very
> beginning with python.

> Here is my module and a corresponding test program:

> # --- color change strings for terminal output ---
> #
> pc_yell = '\033[01;93m'
> pc_purp = '\033[01;33m'
> pc_gren = '\033[01;92m'

Hw lng wld psts + prgrms b wr it nt 4 z art of clvr + ez 2 mmrz 
abbreviations ;)

> # --- Class for all logging functionality ---
> #
> class locLogg():
>    _logger = None

>    def debug_log(self, msg, *args, **kwargs):
>    def warn_log(self, msg, *args, **kwargs):
>    def error_log(self, msg, *args, **kwargs):

It should be easy to factor out most the code in your xxx_log() methods into 
a common helper. 

>    def fatal_log(self, msg, *args, **kwargs):
>      previousFrame = inspect.currentframe().f_back
>      locLogg._logger.fatal(str(level_color['fatal'])+msg+pc_norm + \
>        ' ' + argskw_2_string(*args, **kwargs),
>        extra={'custom_lineno':previousFrame.f_lineno,
>          'custom_filename': previousFrame.f_code.co_filename })

I think the formatting belongs into another layer. That's the purpose of the 
logging.Formatter class. You could enhance it along those lines:

class Formatter(logging.Formatter):
    markers = {
        logging.INFO: ("<info>", "</info>"),
        logging.WARN: ("<warn>", "</warn>"),
    def format(self, record):
        message = logging.Formatter.format(self, record)
            prefix, suffix = self.markers[record.levelno]
        except KeyError:
            message = prefix + message + suffix
        return message

My general impression is that you are fighting the logging library's 
structure rather than trying to use it as effectively as possible.

>    foo.info_log('another bar info', 1,2,3, a=11, b=22, c=44)

You could achieve something similar with a standard logger by passing your 
extra information through the extra parameter, e. g:

def extra(*args, **kw):
   return dict(argskw=(args, kw))
foo.info("another...", extra=extra(1, 2, 3, a=11, b=22))


More information about the Python-list mailing list