Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

'logging' module - multiple messages

0 views
Skip to first unread message

David N. Welton

unread,
Feb 12, 2003, 9:33:34 PM2/12/03
to

[ CC'ing replies to me appreciated - thanks. ]

When I do something like this:


class WFLog:
def __init__(self, name="WF"):
self.log = logging.getLogger(name)
f = logging.Formatter("%(name)s|%(levelname)s|%(message)s" )
h = logging.StreamHandler()
h.setFormatter(f)
self.log.addHandler(h)
self.log.setLevel(logging.DEBUG)
self.log.debug("Logging enabled")

....

wl = WFLog("WF")
wl2 = WFLog("WF.SC")
wl.debug("testing, testing, 1 2 3")
wl2.debug("prova, prova, 1 2 3")

It appears that it prints out a copy for each logger that exists:

WF|DEBUG|Logging enabled
WF.SC|DEBUG|Logging enabled
WF.SC|DEBUG|Logging enabled
WF|DEBUG|?|testing, testing, 1 2 3
WF.SC|DEBUG|?|prova, prova, 1 2 3
WF.SC|DEBUG|?|prova, prova, 1 2 3

Which is annoying. Any way to get it to just do one copy per log
instance?

Thanks for your time,
--
David N. Welton
Consulting: http://www.dedasys.com/
Personal: http://www.dedasys.com/davidw/
Free Software: http://www.dedasys.com/freesoftware/
Apache Tcl: http://tcl.apache.org/

Robin Munn

unread,
Feb 13, 2003, 5:27:35 PM2/13/03
to

If you read the documentation for the logging module at

http://www.python.org/dev/doc/devel/lib/module-logging.html

you will find this in italics at the end of the sixth paragraph: "In
addition to any handlers directly associated with a logger, all handlers
associated with all ancestors of the logger are called to dispatch the
message." The second paragraph of the documentation explains that
"[e]ach instance has a name, and they are conceptually arranged in a
name space hierarchy using dots (periods) as separators. For example, a
logger named 'scan' is the parent of loggers 'scan.text', 'scan.html'
and 'scan.pdf'."

So what's going on is that your "WF" logger is being considered the
parent of "WF.SC" -- so when WF.SC logs a message, WF receives it too.
This will usually be what you want - you could then attach different
handlers to the different elements in the tree (say WF.SC goes to the
screen via a StreamHandler with level CRITICAL, and WF goes to a log
file with level DEBUG, for example). If you really don't want that, you
could create a Filter that checks the name of the logger that produced
the message, like so:

# "Selfish" filter that doesn't listen to its children
class SelfishFilter(logging.Filter):
"""Filter that doesn't allow messages from children"""
def filter(self, record):
return self.name == record.name

Then you would attach this filter to your code like so:

class WFLog:
def __init__(self, name="WF"):
self.log = logging.getLogger(name)
f = logging.Formatter("%(name)s|%(levelname)s|%(message)s" )
h = logging.StreamHandler()

filter = SelfishFilter(name)
h.setFormatter(f)
self.log.addHandler(h)
self.log.addFilter(filter)


self.log.setLevel(logging.DEBUG)
self.log.debug("Logging enabled")

That should give you the behavior you're looking for.

--
Robin Munn <rm...@pobox.com>
http://www.rmunn.com/
PGP key ID: 0x6AFB6838 50FF 2478 CFFB 081A 8338 54F7 845D ACFD 6AFB 6838

David N. Welton

unread,
Feb 14, 2003, 3:36:53 PM2/14/03
to
Robin Munn <rm...@pobox.com> writes:

> David N. Welton <dav...@dedasys.com> wrote:

> > [ CC'ing replies to me appreciated - thanks. ]

> > It appears that it prints out a copy for each logger that exists:

> > WF|DEBUG|Logging enabled
> > WF.SC|DEBUG|Logging enabled
> > WF.SC|DEBUG|Logging enabled
> > WF|DEBUG|?|testing, testing, 1 2 3
> > WF.SC|DEBUG|?|prova, prova, 1 2 3
> > WF.SC|DEBUG|?|prova, prova, 1 2 3

> If you read the documentation for the logging module at

> http://www.python.org/dev/doc/devel/lib/module-logging.html

Aha - I was using the red-dove site, which isn't as thorough.

[ ... ]

Yes, I had assumed it was something similar.

I still get two messages, but that's enough direction to go on to
figure things out. Thanks!

0 new messages