Optional use of logging library module

E

Eric DeWall

In trying to clean up the inevitable debug printing littered through some
code, I started reading up on the 'logging' module. Browsing groups
indicates that the design of the module is controversial but personally I'm
very happy to see such a full-featured logger as part of the standard
distribution. Here's my problem though (using 2.3.3) - I'm trying to write
some reusable classes that _optionally_ use the logging module. So a class
might look like:

class SomeClass:
def __init__( self, logger=None):
self.logger = logger
(...etc.)

User of the class passes in a Logger object they have already set up with
handlers, etc., class simply calls log methods on the logger when
appropriate. But I can't find a way to create a good "null" logging object
that the class can use by default if no Logger is passed in. I'd like a
simple approach that doesn't involve extending the existing logging library.

Options I've considered:

1) if self.logger: self.logger.log( 'some message' ) [throughout class
methods]
Constantly check if the logger exists - what a pain.

2) [in __init__:] if not logger: self.logger = logging.getLogger("null")
This would be great if a "null" logger was directly supported by the library
and set to do nothing. But it's not, so handlers would need to be
installed, and there's no guarantee for "null" to be unique anyway

3) class NullLogger:
def debug(self, msg, *args, **kwargs): pass
def info(self, msg, *args, **kwargs): pass
def warning(self, msg, *args, **kwargs): pass
def error(self, msg, *args, **kwargs): pass
def exception(self, msg, *args): pass
def critical(self, msg, *args, **kwargs): pass
warn = warning
fatal = critical
Works well, but again I'd rather not extend the original library and this to
be imported all over.

I've also looked at ways of creating a separate logging.Manager, but it is
very coupled to logging.Logger for reasons I can't quite understand from
glancing the code.

Any help is kindly appreciated!
--Eric
 
I

Irmen de Jong

Eric said:
User of the class passes in a Logger object they have already set up with
handlers, etc., class simply calls log methods on the logger when
appropriate. But I can't find a way to create a good "null" logging object
that the class can use by default if no Logger is passed in. I'd like a
simple approach that doesn't involve extending the existing logging library.

Try the 'null' object design pattern:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205

--Irmen
 
N

Neil Benn

Eric said:
In trying to clean up the inevitable debug printing littered through some
code, I started reading up on the 'logging' module. Browsing groups
indicates that the design of the module is controversial but personally I'm
very happy to see such a full-featured logger as part of the standard
distribution. Here's my problem though (using 2.3.3) - I'm trying to write
some reusable classes that _optionally_ use the logging module. So a class
might look like:
<snip>

Hello,

This is an idea by you could do this :

* None or some other ID is passed in (ala the void pattern) as
your Logger
* The Logger is created as a genuine logger
* The logger has propagate set to false to stop messages going upwards
* The logger has it's severity level set so that no messages are logged

OR, you could do this

* None or some other ID is passed in (ala the void pattern) as your
Logger
* The Logger is created as a genuine logger
* A filter is created which simply filters out everything

However what I would suggest could be a good solution for you is to
always have a logger present and log debug messages as debug and use the
other levels for what they are meant for WARNING, ERROR, etc. That way
you can easily turn the logger off in the instance you are working
with. Yes, OK you take a small speed knock but the speed knock I've had
on this is small (I'm not a speed junkie anyways).

I also agree with you, a fully featured logger is essential and
personally - I'm happy with the design, it's not too complicated you
only need to read through the docs and try it out - easy peasy lemon
squeezy.

Cheers,

Neil

--

Neil Benn
Senior Automation Engineer
Cenix BioScience
BioInnovations Zentrum
Tatzberg 47
D-01307
Dresden
Germany

Tel : +49 (0)351 4173 154
e-mail : (e-mail address removed)
Cenix Website : http://www.cenix-bioscience.com
 
E

Eric DeWall

Hi Neil,

First off, happy to see someone else with some real appreciation for a
standardized and full-featured logging module! You're preaching to the
choir a bit here - I'm also not a speed freak and I will personally _always_
associate a logger with my class instance. But some folks _don't_
use/like/appreciate the logging module so I'd rather not make it a
requirement for them to use logging to reuse my classes. Irmen's suggestion
of the null pattern elegantly solves my dilemma. And for folks who don't
want logging, they'll still have to handle exceptions when something goes
wrong. :)

--Eric

However what I would suggest could be a good solution for you is to
always have a logger present and log debug messages as debug and use the
other levels for what they are meant for WARNING, ERROR, etc. That way
you can easily turn the logger off in the instance you are working
with. Yes, OK you take a small speed knock but the speed knock I've had
on this is small (I'm not a speed junkie anyways).

I also agree with you, a fully featured logger is essential and
personally - I'm happy with the design, it's not too complicated you
only need to read through the docs and try it out - easy peasy lemon
squeezy.

Cheers,

Neil
<snip>
 
V

Vinay Sajip

associate a logger with my class instance. But some folks _don't_
use/like/appreciate the logging module so I'd rather not make it a
requirement for them to use logging to reuse my classes. Irmen's suggestion

I'm curious to know what people don't like about the logging module. I
haven't seen any posts on c.l.py complaining about it, can you point
me to some discussions?


Vinay Sajip
 
P

Peter Otten

Vinay said:
I'm curious to know what people don't like about the logging module. I
haven't seen any posts on c.l.py complaining about it, can you point
me to some discussions?

First of all: the logging package is *nice*, thank you for providing it.

Here are two older threads that may give you an idea what difficulties
people may encounter when learning to use it:
http://groups.google.com/[email protected]
http://groups.google.com/[email protected]

What I would like to see:

- A one-stop function to get output to a file or stream.

- A standard way to register custom handlers, something like
registerHandlerClass(klass, name=None), name defaulting to klass.__name__.
This would probably imply replacing eval() with a dictionary lookup.

- I find the programmatic interface easier to learn than the config-file
format. A utility function that writes the current configuration to a file
might help here.

- Let config-files and programmatic setup respect each other.

- Allow for multiple root loggers. Logging can be used for totally unrelated
tasks. I feel a little uneasy to have them all in the same hierarchy. (This
one is thinking aloud, I'm not even sure if this cannot be done already
with the Manager class)

None of these are showstoppers, and judging from recent posts on python-dev
you are already working on the first and most important issue.

If you want to attract further suggestions on how to smoothen the logging
experience, from people who are more familiar with the package than I am,
it would probably be a good idea to open up a new thread.

Peter
 
V

Vinay Sajip

Peter,

Thanks for the feedback. My thoughts below...
- A one-stop function to get output to a file or stream.

Now in CVS.
- A standard way to register custom handlers, something like
registerHandlerClass(klass, name=None), name defaulting to klass.__name__.
This would probably imply replacing eval() with a dictionary lookup.

- I find the programmatic interface easier to learn than the config-file
format. A utility function that writes the current configuration to a file
might help here.

- Let config-files and programmatic setup respect each other.

The above are good ideas. By "respect each other", I assume you mean
that file-based configuration should not overwrite programmatic
configuration? The overall problem with file-based configuration is
that it replaces the existing configuration totally. I'm thinking
about a different way of configuring which works in an incremental
way. It's too early to say much about it, though.
- Allow for multiple root loggers. Logging can be used for totally unrelated
tasks. I feel a little uneasy to have them all in the same hierarchy. (This
one is thinking aloud, I'm not even sure if this cannot be done already
with the Manager class)

I'm not sure that you need API changes for this - you can achieve the
same effect through non-propagating non-root loggers. Since you can
direct messages at any point to any destination, you can easily keep
totally separate logs for unrelated tasks.
None of these are showstoppers, and judging from recent posts on python-dev
you are already working on the first and most important issue.

If you want to attract further suggestions on how to smoothen the logging
experience, from people who are more familiar with the package than I am,
it would probably be a good idea to open up a new thread.

Good idea. I'll do this.

Thanks again,


Vinay
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top