|
A standard package for writing logs, logging, has been added to
Python 2.3. It provides a powerful and flexible mechanism for generating logging output
which can then be filtered and processed in various ways. A configuration file written in
a standard format can be used to control the logging behavior of a program. Python
includes handlers that will write log records to standard error or to a file or socket,
send them to the system log, or even e-mail them to a particular address; of course, it's
also possible to write your own handler classes.
The Logger class is the primary class. Most application code
will deal with one or more Logger objects, each one used by a
particular subsystem of the application. Each Logger is identified
by a name, and names are organized into a hierarchy using "."
as the component separator. For example, you might have Logger
instances named "server", "server.auth"
and "server.network". The latter two instances are below
"server" in the hierarchy. This means that if you turn up
the verbosity for "server" or direct "server"messages to a different handler, the changes will also apply
to records logged to "server.auth" and "server.network". There's also a root Logger
that's the parent of all other loggers.
For simple uses, the logging package contains some convenience
functions that always use the root log:
import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')
This produces the following output:
WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down
In the default configuration, informational and debugging messages are suppressed and
the output is sent to standard error. You can enable the display of informational and
debugging messages by calling the setLevel() method on the root
logger.
Notice the warning() call's use of string formatting
operators; all of the functions for logging messages take the arguments (msg,
arg1, arg2, ...) and log the string resulting from msg
% (arg1, arg2, ...).
There's also an exception() function that records the most
recent traceback. Any of the other functions will also record the traceback if you specify
a true value for the keyword argument exc_info.
def f():
try: 1/0
except: logging.exception('Problem recorded')
f()
This produces the following output:
ERROR:root:Problem recorded
Traceback (most recent call last):
File "t.py", line 6, in f
1/0
ZeroDivisionError: integer division or modulo by zero
Slightly more advanced programs will use a logger other than the root logger. The getLogger(name) function is used to get a particular log,
creating it if it doesn't exist yet. getLogger(None) returns the
root logger.
log = logging.getLogger('server')
...
log.info('Listening on port %i', port)
...
log.critical('Disk full')
...
Log records are usually propagated up the hierarchy, so a message logged to "server.auth" is also seen by "server"
and "root", but a Logger can
prevent this by setting its propagate attribute to False.
There are more classes provided by the logging package that can
be customized. When a Logger instance is told to log a message, it
creates a LogRecord instance that is sent to any number of
different Handler instances. Loggers and handlers can also have an
attached list of filters, and each filter can cause the LogRecord
to be ignored or can modify the record before passing it along. When they're finally
output, LogRecord instances are converted to text by a Formatter class. All of these classes can be replaced by your own
specially-written classes.
With all of these features the logging package should provide
enough flexibility for even the most complicated applications. This is only an incomplete
overview of its features, so please see the package's reference documentation for all of the
details. Reading PEP 282 will also be helpful.
|