logging module example

Diez B. Roggisch deets at nospam.web.de
Sat Dec 31 12:53:16 EST 2005


Chris Smith schrieb:
> Hola, pythonisas:
>  The documentation for the logging module is good, but a bit obscure.
>  In particular, there seems to be a lot of action at a distance.
>  The fact that getLogger() can actually be a call to Logger.__init__(),
> which is mentioned in para 6.29.1, also bears stressing on 6.29.  I
> grasp _why_ you'd implement it that way, but I may not be the only
> coder who feels queasy with the word 'get' being used both to fetch
> an instance and to trigger instantiation.

The reason for this "distance" is simply that you should be able to get 
a grip on a logger from wherever you are, explicitly _without_ first 
having to instantiate it and possibly pass it around. Think of this 
little example:

class Mixin(object):
     def foo(self):
         logger = logging.getLogger("MixinLogger")
         logger.debug("I'm foo!")

     def bar(self):
         logger = logging.getLogger("MixinLogger")
         logger.debug("I'm bar!")

class User(Mixin):

     def some_random_method(self):
         if relative_moon_humidity() > .8:
             self.foo()
         else:
             self.bar()


So the decoupling makes lots of sense in logging IMHO.

>  Anyway, after poring over the documentation, unit test, and source code,
> I'd like to show a sample script that will eventually be used 
> in my vanity project, with four loggers of increasing granularity.
>  I realize there are probably more ways to do this (logging seemingly
> sporting perl-esque flexibility ;) so please weigh in with thoughts.
>  Perhaps now I can go back and get this to work with the
> logging.config interface. :)

> forest = ["root","trunk","branch","leaf"]
> #relate our logger names to levels
> lumber_jack = {forest[0] : logging.DEBUG
>               ,forest[1] : logging.INFO
>               ,forest[2] : logging.WARNING
>               ,forest[3] : logging.ERROR  }
> #Used to build up the log names into a hierarchy
> log_name = []
> 
> for log in forest:
>     mounty  = logging.FileHandler("%s%s.txt" % ("/home/smitty/mddl/",log))
>     log_name.append(log)
>     print "Instantiating %s"  % ".".join(log_name)
>     timber  = logging.getLogger(".".join(log_name))
>     timber.setLevel(lumber_jack[log])
>     timber.addHandler(mounty)
>     if   lumber_jack[log] == logging.DEBUG:
>         timber.debug(  "%s's a lumberjack, and he's OK." % log)
>     elif lumber_jack[log] == logging.INFO:
>         timber.info(   "%s's a lumberjack, and he's OK." % log)
>     elif lumber_jack[log] == logging.WARNING:
>         timber.warning("%s's a lumberjack, and he's OK." % log)
>     elif lumber_jack[log] == logging.ERROR:

That looks as an misunderstanding or somewhat strange usage of the 
logging-api. It is _very_ uncommon to have loggers level depending on 
_data_. Instead you just invoke

logger.debug(some_data)

and set the level elsewhere. That is a somewhat static rleationship - 
all forests are supposed to share _one_ logging instance, with it's 
current log-level. And you don't check for the level being DEBUG or 
whatever. You just log, and if the level is above (or below, whatever 
stance you take) the currently set level for that logger, the message 
gets displayed.

All in all it seems that you have some difficulties with the loggers 
being a sort of global objects. Keep that in mind when developing using 
them.

Regards,

Diez



More information about the Python-list mailing list