Welcome, guest | Sign In | My Account | Store | Cart

This amazingly powerful module is a mystery to novices. Once you figure it out, you'll use it everywhere.

In addition to examples, here are a couple of useful filters.

Python, 74 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import logging

class Opaque(logging.Filter):
    """A simple way to prevent any messages from getting through."""
    def __init__(self, name=None): pass
    def filter(self, rec): return False

class Unique(logging.Filter):
    """Messages are allowed through just once.
    The 'message' includes substitutions, but is not formatted by the 
    handler. If it were, then practically all messages would be unique!
    """
    def __init__(self, name=""):
        logging.Filter.__init__(self, name)
        self.reset()
    def reset(self):
        """Act as if nothing has happened."""
        self.__logged = {}
    def filter(self, rec):
        """logging.Filter.filter performs an extra filter on the name."""
        return logging.Filter.filter(self, rec) and self.__is_first_time(rec)
    def __is_first_time(self, rec):
        """Emit a message only once."""
        msg = rec.msg %(rec.args)
        if msg in self.__logged:
            self.__logged[msg] += 1
            return False
        else:
            self.__logged[msg] = 1
            return True

logging.warning("I am the root logger")
logging.getLogger().name = ""
logging.warning("I am the root logger")
logging.getLogger().name = "RootOfAllEvil" # You can use any name for the root.
logging.warning("I am the root logger")
logging.getLogger().name = "." # I like to use dot for the root
logging.warning("I am the root logger")
# Unfortunately, logging.getLogger() != logging.getLogger(".") # Bug?

logger = logging.getLogger(".child")
logger.warning("I am a child who repeats things.")
logger.warning("I am a child who repeats things.")

unique = Unique()
logger.addFilter(unique)
logger.warning("You only need to hear this once.")
logger.warning("You only need to hear this once.")

logger.warning("But this is worth repeating.")
unique.reset()
logger.warning("But this is worth repeating.")
logger.warning("But this is worth repeating.")

opaque = Opaque()
logger.addFilter(opaque)
logger.warning("You should never see this.")

logger.removeFilter(opaque)
logger.warning("You should see this just once.")
logger.warning("You should see this just once.")

sublogger = logging.getLogger(".child.grandchild")
sublogger.warning("This is not filtered by the parent logger.")
sublogger.warning("This is not filtered by the parent logger.")

handler = logging.StreamHandler()
formatter = logging.Formatter("EXTRA:%(name)s:'%(message)s'")
handler.setFormatter(formatter)
handler.addFilter(Unique()) #new instance of the Unique filter
logger.addHandler(handler)

sublogger.warning("But this *is* filtered by the parent's handlers.")
sublogger.warning("But this *is* filtered by the parent's handlers.")
Hierarchy of loggers

It is very easy to use separate loggers to make specific sub-system debugging easier. You don't even have to pass the logger objects between modules; just use getLogger("my.hierarchical.name"). Messages sent to that logger would be handled by itself, then (if not removed by filters) by handlers of any parents, in order.

The root logger is the root parent of all loggers, so you can handle any unfiltered messages in your main program by accessing <pre>logging.getLogger()</pre> or <pre>logging.root #deprecated</pre> You can even rename the root logger for pretty-printing. (That is currently an undocumented feature. However, you cannot access the root logger by that name via getLogger(rootName). That would actually yield a different logger. This may be clarified in a future release, I'm told.)

Handlers, Formatters, and Filters

The simplest way to create a handler is just to use one of logging's global functions, e.g. <pre>logging.info("Create a default handler.)</pre> The 2nd-easiest way is to call <pre>logging.basicConfig()</pre> (which is called implicitly if you use a global function without first adding your own handlers).

Eventually, you will want to add your own handlers, formatters, and filters. (logging.handlers.SMTPHandler is particularly amazing.) Note that a filter on a logger applies only to messages sent directly to that logger, whereas a filter on a handler applies also to messages received from child loggers.

When using filters, be careful to create new instances if that is what you want. Also, if you plan to remove a filter, you must retain a reference, since you cannot remove the filter without having it. Also, you may sometimes wish to reset() the cache of a Unique filter.

But if you use the Unique filter, be careful of instances. If the same instance is applied to both a logger and its handler, then nothing will be emitted by that handler.

The code (should) result in this: <pre> WARNING:root:I am the root logger WARNING::I am the root logger WARNING:RootOfAllEvil:I am the root logger WARNING:.:I am the root logger WARNING:.child:I am a child who repeats things. WARNING:.child:I am a child who repeats things. WARNING:.child:You only need to hear this once. WARNING:.child:But this is worth repeating. WARNING:.child:But this is worth repeating. WARNING:.child:You should see this just once. WARNING:.child.grandchild:This is not filtered by the parent logger. WARNING:.child.grandchild:This is not filtered by the parent logger. EXTRA:.child.grandchild:'But this is filtered by the parent's handlers.' WARNING:.child.grandchild:But this is filtered by the parent's handlers. WARNING:.child.grandchild:But this is filtered by the parent's handlers. </pre> [See also: "Generic filter logic strategy" or "handler stack" for ideas not directly related to the logging module, but to filter and log-handler strategies.]

Created by Christopher Dunn on Thu, 28 Apr 2005 (PSF)
Python recipes (4591)
Christopher Dunn's recipes (5)

Required Modules

Other Information and Tasks