reSTify PEP 282 (#358)
This commit is contained in:
parent
a5101b1988
commit
f22e81b255
190
pep-0282.txt
190
pep-0282.txt
|
@ -2,16 +2,17 @@ PEP: 282
|
||||||
Title: A Logging System
|
Title: A Logging System
|
||||||
Version: $Revision$
|
Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: vinay_sajip at red-dove.com (Vinay Sajip),
|
Author: vinay_sajip at red-dove.com (Vinay Sajip), trentm@activestate.com (Trent Mick)
|
||||||
trentm@activestate.com (Trent Mick)
|
|
||||||
Status: Final
|
Status: Final
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 4-Feb-2002
|
Created: 4-Feb-2002
|
||||||
Python-Version: 2.3
|
Python-Version: 2.3
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
This PEP describes a proposed logging package for Python's
|
This PEP describes a proposed logging package for Python's
|
||||||
standard library.
|
standard library.
|
||||||
|
@ -36,6 +37,7 @@ Abstract
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
Motivation
|
||||||
|
==========
|
||||||
|
|
||||||
If a single logging mechanism is enshrined in the standard
|
If a single logging mechanism is enshrined in the standard
|
||||||
library, 1) logging is more likely to be done 'well', and 2)
|
library, 1) logging is more likely to be done 'well', and 2)
|
||||||
|
@ -44,21 +46,25 @@ Motivation
|
||||||
|
|
||||||
|
|
||||||
Influences
|
Influences
|
||||||
|
==========
|
||||||
|
|
||||||
This proposal was put together after having studied the
|
This proposal was put together after having studied the
|
||||||
following logging packages:
|
following logging packages:
|
||||||
|
|
||||||
o java.util.logging in JDK 1.4 (a.k.a. JSR047) [1]
|
* java.util.logging in JDK 1.4 (a.k.a. JSR047) [1]_
|
||||||
o log4j [2]
|
* log4j [2]_
|
||||||
o the Syslog package from the Protomatter project [3]
|
* the Syslog package from the Protomatter project [3]_
|
||||||
o MAL's mx.Log package [4]
|
* MAL's mx.Log package [4]_
|
||||||
|
|
||||||
|
|
||||||
Simple Example
|
Simple Example
|
||||||
|
==============
|
||||||
|
|
||||||
This shows a very simple example of how the logging package can be
|
This shows a very simple example of how the logging package can be
|
||||||
used to generate simple logging output on stderr.
|
used to generate simple logging output on stderr.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
--------- mymodule.py -------------------------------
|
--------- mymodule.py -------------------------------
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger("MyModule")
|
log = logging.getLogger("MyModule")
|
||||||
|
@ -100,7 +106,7 @@ Simple Example
|
||||||
|
|
||||||
The above example shows the default output format. All
|
The above example shows the default output format. All
|
||||||
aspects of the output format should be configurable, so that
|
aspects of the output format should be configurable, so that
|
||||||
you could have output formatted like this:
|
you could have output formatted like this::
|
||||||
|
|
||||||
2002-04-19 07:56:58,174 MyModule DEBUG - Doin' stuff...
|
2002-04-19 07:56:58,174 MyModule DEBUG - Doin' stuff...
|
||||||
|
|
||||||
|
@ -110,8 +116,9 @@ Simple Example
|
||||||
|
|
||||||
|
|
||||||
Control Flow
|
Control Flow
|
||||||
|
============
|
||||||
|
|
||||||
Applications make logging calls on *Logger* objects. Loggers are
|
Applications make logging calls on **Logger** objects. Loggers are
|
||||||
organized in a hierarchical namespace and child Loggers inherit
|
organized in a hierarchical namespace and child Loggers inherit
|
||||||
some logging properties from their parents in the namespace.
|
some logging properties from their parents in the namespace.
|
||||||
|
|
||||||
|
@ -119,16 +126,18 @@ Control Flow
|
||||||
(periods) indicating sub-namespaces. The namespace of logger
|
(periods) indicating sub-namespaces. The namespace of logger
|
||||||
objects therefore corresponds to a single tree data structure.
|
objects therefore corresponds to a single tree data structure.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
"" is the root of the namespace
|
"" is the root of the namespace
|
||||||
"Zope" would be a child node of the root
|
"Zope" would be a child node of the root
|
||||||
"Zope.ZODB" would be a child node of "Zope"
|
"Zope.ZODB" would be a child node of "Zope"
|
||||||
|
|
||||||
These Logger objects create *LogRecord* objects which are passed
|
These Logger objects create **LogRecord** objects which are passed
|
||||||
to *Handler* objects for output. Both Loggers and Handlers may
|
to **Handler** objects for output. Both Loggers and Handlers may
|
||||||
use logging *levels* and (optionally) *Filters* to decide if they
|
use logging **levels** and (optionally) **Filters** to decide if they
|
||||||
are interested in a particular LogRecord. When it is necessary to
|
are interested in a particular LogRecord. When it is necessary to
|
||||||
output a LogRecord externally, a Handler can (optionally) use a
|
output a LogRecord externally, a Handler can (optionally) use a
|
||||||
*Formatter* to localize and format the message before sending it
|
**Formatter** to localize and format the message before sending it
|
||||||
to an I/O stream.
|
to an I/O stream.
|
||||||
|
|
||||||
Each Logger keeps track of a set of output Handlers. By default
|
Each Logger keeps track of a set of output Handlers. By default
|
||||||
|
@ -147,7 +156,7 @@ Control Flow
|
||||||
|
|
||||||
The overall Logger hierarchy can also have a level associated with
|
The overall Logger hierarchy can also have a level associated with
|
||||||
it, which takes precedence over the levels of individual Loggers.
|
it, which takes precedence over the levels of individual Loggers.
|
||||||
This is done through a module-level function:
|
This is done through a module-level function::
|
||||||
|
|
||||||
def disable(lvl):
|
def disable(lvl):
|
||||||
"""
|
"""
|
||||||
|
@ -158,8 +167,9 @@ Control Flow
|
||||||
|
|
||||||
|
|
||||||
Levels
|
Levels
|
||||||
|
======
|
||||||
|
|
||||||
The logging levels, in increasing order of importance, are:
|
The logging levels, in increasing order of importance, are::
|
||||||
|
|
||||||
DEBUG
|
DEBUG
|
||||||
INFO
|
INFO
|
||||||
|
@ -188,7 +198,7 @@ Levels
|
||||||
increasing severity.
|
increasing severity.
|
||||||
|
|
||||||
User-defined logging levels are supported through two module-level
|
User-defined logging levels are supported through two module-level
|
||||||
functions:
|
functions::
|
||||||
|
|
||||||
def getLevelName(lvl):
|
def getLevelName(lvl):
|
||||||
"""Return the text for level 'lvl'."""
|
"""Return the text for level 'lvl'."""
|
||||||
|
@ -202,11 +212,12 @@ Levels
|
||||||
...
|
...
|
||||||
|
|
||||||
Loggers
|
Loggers
|
||||||
|
=======
|
||||||
|
|
||||||
Each Logger object keeps track of a log level (or threshold) that
|
Each Logger object keeps track of a log level (or threshold) that
|
||||||
it is interested in, and discards log requests below that level.
|
it is interested in, and discards log requests below that level.
|
||||||
|
|
||||||
A *Manager* class instance maintains the hierarchical namespace of
|
A **Manager** class instance maintains the hierarchical namespace of
|
||||||
named Logger objects. Generations are denoted with dot-separated
|
named Logger objects. Generations are denoted with dot-separated
|
||||||
names: Logger "foo" is the parent of Loggers "foo.bar" and
|
names: Logger "foo" is the parent of Loggers "foo.bar" and
|
||||||
"foo.baz".
|
"foo.baz".
|
||||||
|
@ -215,14 +226,14 @@ Loggers
|
||||||
exposed to users, who interact with it using various module-level
|
exposed to users, who interact with it using various module-level
|
||||||
functions.
|
functions.
|
||||||
|
|
||||||
The general logging method is:
|
The general logging method is::
|
||||||
|
|
||||||
class Logger:
|
class Logger:
|
||||||
def log(self, lvl, msg, *args, **kwargs):
|
def log(self, lvl, msg, *args, **kwargs):
|
||||||
"""Log 'str(msg) % args' at logging level 'lvl'."""
|
"""Log 'str(msg) % args' at logging level 'lvl'."""
|
||||||
...
|
...
|
||||||
|
|
||||||
However, convenience functions are defined for each logging level:
|
However, convenience functions are defined for each logging level::
|
||||||
|
|
||||||
class Logger:
|
class Logger:
|
||||||
def debug(self, msg, *args, **kwargs): ...
|
def debug(self, msg, *args, **kwargs): ...
|
||||||
|
@ -234,10 +245,10 @@ Loggers
|
||||||
Only one keyword argument is recognized at present - "exc_info".
|
Only one keyword argument is recognized at present - "exc_info".
|
||||||
If true, the caller wants exception information to be provided in
|
If true, the caller wants exception information to be provided in
|
||||||
the logging output. This mechanism is only needed if exception
|
the logging output. This mechanism is only needed if exception
|
||||||
information needs to be provided at *any* logging level. In the
|
information needs to be provided at **any** logging level. In the
|
||||||
more common case, where exception information needs to be added to
|
more common case, where exception information needs to be added to
|
||||||
the log only when errors occur, i.e. at the ERROR level, then
|
the log only when errors occur, i.e. at the ERROR level, then
|
||||||
another convenience method is provided:
|
another convenience method is provided::
|
||||||
|
|
||||||
class Logger:
|
class Logger:
|
||||||
def exception(self, msg, *args): ...
|
def exception(self, msg, *args): ...
|
||||||
|
@ -250,11 +261,11 @@ Loggers
|
||||||
context of an INFO message, for example.
|
context of an INFO message, for example.
|
||||||
|
|
||||||
The "msg" argument shown above will normally be a format string;
|
The "msg" argument shown above will normally be a format string;
|
||||||
however, it can be any object x for which str(x) returns the
|
however, it can be any object x for which ``str(x)`` returns the
|
||||||
format string. This facilitates, for example, the use of an
|
format string. This facilitates, for example, the use of an
|
||||||
object which fetches a locale- specific message for an
|
object which fetches a locale- specific message for an
|
||||||
internationalized/localized application, perhaps using the
|
internationalized/localized application, perhaps using the
|
||||||
standard gettext module. An outline example:
|
standard gettext module. An outline example::
|
||||||
|
|
||||||
class Message:
|
class Message:
|
||||||
"""Represents a message"""
|
"""Represents a message"""
|
||||||
|
@ -271,7 +282,7 @@ Loggers
|
||||||
Gathering and formatting data for a log message may be expensive,
|
Gathering and formatting data for a log message may be expensive,
|
||||||
and a waste if the logger was going to discard the message anyway.
|
and a waste if the logger was going to discard the message anyway.
|
||||||
To see if a request will be honoured by the logger, the
|
To see if a request will be honoured by the logger, the
|
||||||
isEnabledFor() method can be used:
|
``isEnabledFor()`` method can be used::
|
||||||
|
|
||||||
class Logger:
|
class Logger:
|
||||||
def isEnabledFor(self, lvl):
|
def isEnabledFor(self, lvl):
|
||||||
|
@ -282,14 +293,14 @@ Loggers
|
||||||
...
|
...
|
||||||
|
|
||||||
so instead of this expensive and possibly wasteful DOM to XML
|
so instead of this expensive and possibly wasteful DOM to XML
|
||||||
conversion:
|
conversion::
|
||||||
|
|
||||||
...
|
...
|
||||||
hamletStr = hamletDom.toxml()
|
hamletStr = hamletDom.toxml()
|
||||||
log.info(hamletStr)
|
log.info(hamletStr)
|
||||||
...
|
...
|
||||||
|
|
||||||
one can do this:
|
one can do this::
|
||||||
|
|
||||||
if log.isEnabledFor(logging.INFO):
|
if log.isEnabledFor(logging.INFO):
|
||||||
hamletStr = hamletDom.toxml()
|
hamletStr = hamletDom.toxml()
|
||||||
|
@ -297,7 +308,7 @@ Loggers
|
||||||
|
|
||||||
When new loggers are created, they are initialized with a level
|
When new loggers are created, they are initialized with a level
|
||||||
which signifies "no level". A level can be set explicitly using
|
which signifies "no level". A level can be set explicitly using
|
||||||
the setLevel() method:
|
the ``setLevel()`` method::
|
||||||
|
|
||||||
class Logger:
|
class Logger:
|
||||||
def setLevel(self, lvl): ...
|
def setLevel(self, lvl): ...
|
||||||
|
@ -305,12 +316,12 @@ Loggers
|
||||||
If a logger's level is not set, the system consults all its
|
If a logger's level is not set, the system consults all its
|
||||||
ancestors, walking up the hierarchy until an explicitly set level
|
ancestors, walking up the hierarchy until an explicitly set level
|
||||||
is found. That is regarded as the "effective level" of the
|
is found. That is regarded as the "effective level" of the
|
||||||
logger, and can be queried via the getEffectiveLevel() method:
|
logger, and can be queried via the getEffectiveLevel() method::
|
||||||
|
|
||||||
def getEffectiveLevel(self): ...
|
def getEffectiveLevel(self): ...
|
||||||
|
|
||||||
Loggers are never instantiated directly. Instead, a module-level
|
Loggers are never instantiated directly. Instead, a module-level
|
||||||
function is used:
|
function is used::
|
||||||
|
|
||||||
def getLogger(name=None): ...
|
def getLogger(name=None): ...
|
||||||
|
|
||||||
|
@ -320,37 +331,38 @@ Loggers
|
||||||
with "channel name".
|
with "channel name".
|
||||||
|
|
||||||
Users can specify a custom subclass of Logger to be used by the
|
Users can specify a custom subclass of Logger to be used by the
|
||||||
system when instantiating new loggers:
|
system when instantiating new loggers::
|
||||||
|
|
||||||
def setLoggerClass(klass): ...
|
def setLoggerClass(klass): ...
|
||||||
|
|
||||||
The passed class should be a subclass of Logger, and its __init__
|
The passed class should be a subclass of Logger, and its ``__init__``
|
||||||
method should call Logger.__init__.
|
method should call ``Logger.__init__``.
|
||||||
|
|
||||||
|
|
||||||
Handlers
|
Handlers
|
||||||
|
========
|
||||||
|
|
||||||
Handlers are responsible for doing something useful with a given
|
Handlers are responsible for doing something useful with a given
|
||||||
LogRecord. The following core Handlers will be implemented:
|
``LogRecord``. The following core Handlers will be implemented:
|
||||||
|
|
||||||
- StreamHandler: A handler for writing to a file-like object.
|
- ``StreamHandler``: A handler for writing to a file-like object.
|
||||||
- FileHandler: A handler for writing to a single file or set
|
- ``FileHandler``: A handler for writing to a single file or set
|
||||||
of rotating files.
|
of rotating files.
|
||||||
- SocketHandler: A handler for writing to remote TCP ports.
|
- ``SocketHandler``: A handler for writing to remote TCP ports.
|
||||||
- DatagramHandler: A handler for writing to UDP sockets, for
|
- ``DatagramHandler``: A handler for writing to UDP sockets, for
|
||||||
low-cost logging. Jeff Bauer already had such a system [5].
|
low-cost logging. Jeff Bauer already had such a system [5]_.
|
||||||
- MemoryHandler: A handler that buffers log records in memory
|
- ``MemoryHandler``: A handler that buffers log records in memory
|
||||||
until the buffer is full or a particular condition occurs
|
until the buffer is full or a particular condition occurs
|
||||||
[1].
|
[1]_.
|
||||||
- SMTPHandler: A handler for sending to email addresses via SMTP.
|
- ``SMTPHandler``: A handler for sending to email addresses via SMTP.
|
||||||
- SysLogHandler: A handler for writing to Unix syslog via UDP.
|
- ``SysLogHandler``: A handler for writing to Unix syslog via UDP.
|
||||||
- NTEventLogHandler: A handler for writing to event logs on
|
- ``NTEventLogHandler``: A handler for writing to event logs on
|
||||||
Windows NT, 2000 and XP.
|
Windows NT, 2000 and XP.
|
||||||
- HTTPHandler: A handler for writing to a Web server with
|
- ``HTTPHandler``: A handler for writing to a Web server with
|
||||||
either GET or POST semantics.
|
either GET or POST semantics.
|
||||||
|
|
||||||
Handlers can also have levels set for them using the
|
Handlers can also have levels set for them using the
|
||||||
setLevel() method:
|
``setLevel()`` method::
|
||||||
|
|
||||||
def setLevel(self, lvl): ...
|
def setLevel(self, lvl): ...
|
||||||
|
|
||||||
|
@ -363,6 +375,8 @@ Handlers
|
||||||
The setRollover method is used to specify a maximum size for a log
|
The setRollover method is used to specify a maximum size for a log
|
||||||
file and a maximum number of backup files in the rotation.
|
file and a maximum number of backup files in the rotation.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
def setRollover(maxBytes, backupCount): ...
|
def setRollover(maxBytes, backupCount): ...
|
||||||
|
|
||||||
If maxBytes is specified as zero, no rollover ever occurs and the
|
If maxBytes is specified as zero, no rollover ever occurs and the
|
||||||
|
@ -373,72 +387,76 @@ Handlers
|
||||||
that, and so on.
|
that, and so on.
|
||||||
|
|
||||||
There are many additional handlers implemented in the test/example
|
There are many additional handlers implemented in the test/example
|
||||||
scripts provided with [6] - for example, XMLHandler and
|
scripts provided with [6]_ - for example, XMLHandler and
|
||||||
SOAPHandler.
|
SOAPHandler.
|
||||||
|
|
||||||
|
|
||||||
LogRecords
|
LogRecords
|
||||||
|
==========
|
||||||
|
|
||||||
A LogRecord acts as a receptacle for information about a
|
A LogRecord acts as a receptacle for information about a
|
||||||
logging event. It is little more than a dictionary, though it
|
logging event. It is little more than a dictionary, though it
|
||||||
does define a getMessage method which merges a message with
|
does define a ``getMessage`` method which merges a message with
|
||||||
optional runarguments.
|
optional runarguments.
|
||||||
|
|
||||||
|
|
||||||
Formatters
|
Formatters
|
||||||
|
==========
|
||||||
|
|
||||||
A Formatter is responsible for converting a LogRecord to a string
|
A Formatter is responsible for converting a LogRecord to a string
|
||||||
representation. A Handler may call its Formatter before writing a
|
representation. A Handler may call its Formatter before writing a
|
||||||
record. The following core Formatters will be implemented:
|
record. The following core Formatters will be implemented:
|
||||||
|
|
||||||
- Formatter: Provide printf-like formatting, using the % operator.
|
- ``Formatter``: Provide printf-like formatting, using the % operator.
|
||||||
|
|
||||||
- BufferingFormatter: Provide formatting for multiple
|
- ``BufferingFormatter``: Provide formatting for multiple
|
||||||
messages, with header and trailer formatting support.
|
messages, with header and trailer formatting support.
|
||||||
|
|
||||||
Formatters are associated with Handlers by calling setFormatter()
|
Formatters are associated with Handlers by calling ``setFormatter()``
|
||||||
on a handler:
|
on a handler::
|
||||||
|
|
||||||
def setFormatter(self, form): ...
|
def setFormatter(self, form): ...
|
||||||
|
|
||||||
Formatters use the % operator to format the logging message. The
|
Formatters use the % operator to format the logging message. The
|
||||||
format string should contain %(name)x and the attribute dictionary
|
format string should contain ``%(name)x`` and the attribute dictionary
|
||||||
of the LogRecord is used to obtain message-specific data. The
|
of the LogRecord is used to obtain message-specific data. The
|
||||||
following attributes are provided:
|
following attributes are provided:
|
||||||
|
|
||||||
%(name)s Name of the logger (logging channel)
|
======================= ======================================================
|
||||||
|
``%(name)s`` Name of the logger (logging channel)
|
||||||
|
|
||||||
%(levelno)s Numeric logging level for the message (DEBUG,
|
``%(levelno)s`` Numeric logging level for the message (DEBUG,
|
||||||
INFO, WARN, ERROR, CRITICAL)
|
INFO, WARN, ERROR, CRITICAL)
|
||||||
|
|
||||||
%(levelname)s Text logging level for the message ("DEBUG", "INFO",
|
``%(levelname)s`` Text logging level for the message ("DEBUG", "INFO",
|
||||||
"WARN", "ERROR", "CRITICAL")
|
"WARN", "ERROR", "CRITICAL")
|
||||||
|
|
||||||
%(pathname)s Full pathname of the source file where the logging
|
``%(pathname)s`` Full pathname of the source file where the logging
|
||||||
call was issued (if available)
|
call was issued (if available)
|
||||||
|
|
||||||
%(filename)s Filename portion of pathname
|
``%(filename)s`` Filename portion of pathname
|
||||||
|
|
||||||
%(module)s Module from which logging call was made
|
``%(module)s`` Module from which logging call was made
|
||||||
|
|
||||||
%(lineno)d Source line number where the logging call was issued
|
``%(lineno)d`` Source line number where the logging call was issued
|
||||||
(if available)
|
(if available)
|
||||||
|
|
||||||
%(created)f Time when the LogRecord was created (time.time()
|
``%(created)f`` Time when the LogRecord was created (``time.time()``
|
||||||
return value)
|
return value)
|
||||||
|
|
||||||
%(asctime)s Textual time when the LogRecord was created
|
``%(asctime)s`` Textual time when the LogRecord was created
|
||||||
|
|
||||||
%(msecs)d Millisecond portion of the creation time
|
``%(msecs)d`` Millisecond portion of the creation time
|
||||||
|
|
||||||
%(relativeCreated)d Time in milliseconds when the LogRecord was created,
|
``%(relativeCreated)d`` Time in milliseconds when the LogRecord was created,
|
||||||
relative to the time the logging module was loaded
|
relative to the time the logging module was loaded
|
||||||
(typically at application startup time)
|
(typically at application startup time)
|
||||||
|
|
||||||
%(thread)d Thread ID (if available)
|
``%(thread)d`` Thread ID (if available)
|
||||||
|
|
||||||
%(message)s The result of record.getMessage(), computed just as
|
``%(message)s`` The result of record.getMessage(), computed just as
|
||||||
the record is emitted
|
the record is emitted
|
||||||
|
======================= ======================================================
|
||||||
|
|
||||||
If a formatter sees that the format string includes "(asctime)s",
|
If a formatter sees that the format string includes "(asctime)s",
|
||||||
the creation time is formatted into the LogRecord's asctime
|
the creation time is formatted into the LogRecord's asctime
|
||||||
|
@ -458,12 +476,15 @@ Formatters
|
||||||
|
|
||||||
|
|
||||||
Filters
|
Filters
|
||||||
|
=======
|
||||||
|
|
||||||
When level-based filtering is insufficient, a Filter can be called
|
When level-based filtering is insufficient, a Filter can be called
|
||||||
by a Logger or Handler to decide if a LogRecord should be output.
|
by a Logger or Handler to decide if a LogRecord should be output.
|
||||||
Loggers and Handlers can have multiple filters installed, and any
|
Loggers and Handlers can have multiple filters installed, and any
|
||||||
one of them can veto a LogRecord being output.
|
one of them can veto a LogRecord being output.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
class Filter:
|
class Filter:
|
||||||
def filter(self, record):
|
def filter(self, record):
|
||||||
"""
|
"""
|
||||||
|
@ -483,10 +504,11 @@ Filters
|
||||||
application; the focus can be changed simply by changing a filter
|
application; the focus can be changed simply by changing a filter
|
||||||
attached to the root logger.
|
attached to the root logger.
|
||||||
|
|
||||||
There are many examples of Filters provided in [6].
|
There are many examples of Filters provided in [6]_.
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
|
=============
|
||||||
|
|
||||||
The main benefit of a logging system like this is that one can
|
The main benefit of a logging system like this is that one can
|
||||||
control how much and what logging output one gets from an
|
control how much and what logging output one gets from an
|
||||||
|
@ -511,9 +533,11 @@ Configuration
|
||||||
|
|
||||||
The most simple configuration is that of a single handler, writing
|
The most simple configuration is that of a single handler, writing
|
||||||
to stderr, attached to the root logger. This configuration is set
|
to stderr, attached to the root logger. This configuration is set
|
||||||
up by calling the basicConfig() function once the logging module
|
up by calling the ``basicConfig()`` function once the logging module
|
||||||
has been imported.
|
has been imported.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
def basicConfig(): ...
|
def basicConfig(): ...
|
||||||
|
|
||||||
For more sophisticated configurations, this PEP makes no specific
|
For more sophisticated configurations, this PEP makes no specific
|
||||||
|
@ -524,12 +548,12 @@ Configuration
|
||||||
Python community, there is no way to know whether any given
|
Python community, there is no way to know whether any given
|
||||||
configuration approach is a good one. That practice can't
|
configuration approach is a good one. That practice can't
|
||||||
really come until the logging module is used, and that means
|
really come until the logging module is used, and that means
|
||||||
until *after* Python 2.3 has shipped.
|
until **after** Python 2.3 has shipped.
|
||||||
- There is a likelihood that different types of applications
|
- There is a likelihood that different types of applications
|
||||||
may require different configuration approaches, so that no
|
may require different configuration approaches, so that no
|
||||||
"one size fits all".
|
"one size fits all".
|
||||||
|
|
||||||
The reference implementation [6] has a working configuration file
|
The reference implementation [6]_ has a working configuration file
|
||||||
format, implemented for the purpose of proving the concept and
|
format, implemented for the purpose of proving the concept and
|
||||||
suggesting one possible alternative. It may be that separate
|
suggesting one possible alternative. It may be that separate
|
||||||
extension modules, not part of the core Python distribution, are
|
extension modules, not part of the core Python distribution, are
|
||||||
|
@ -539,23 +563,25 @@ Configuration
|
||||||
|
|
||||||
|
|
||||||
Thread Safety
|
Thread Safety
|
||||||
|
=============
|
||||||
|
|
||||||
The logging system should support thread-safe operation without
|
The logging system should support thread-safe operation without
|
||||||
any special action needing to be taken by its users.
|
any special action needing to be taken by its users.
|
||||||
|
|
||||||
|
|
||||||
Module-Level Functions
|
Module-Level Functions
|
||||||
|
======================
|
||||||
|
|
||||||
To support use of the logging mechanism in short scripts and small
|
To support use of the logging mechanism in short scripts and small
|
||||||
applications, module-level functions debug(), info(), warn(),
|
applications, module-level functions ``debug()``, ``info()``, ``warn()``,
|
||||||
error(), critical() and exception() are provided. These work in
|
``error()``, ``critical()`` and ``exception()`` are provided. These work in
|
||||||
the same way as the correspondingly named methods of Logger - in
|
the same way as the correspondingly named methods of Logger - in
|
||||||
fact they delegate to the corresponding methods on the root
|
fact they delegate to the corresponding methods on the root
|
||||||
logger. A further convenience provided by these functions is that
|
logger. A further convenience provided by these functions is that
|
||||||
if no configuration has been done, basicConfig() is automatically
|
if no configuration has been done, ``basicConfig()`` is automatically
|
||||||
called.
|
called.
|
||||||
|
|
||||||
At application exit, all handlers can be flushed by calling the function
|
At application exit, all handlers can be flushed by calling the function::
|
||||||
|
|
||||||
def shutdown(): ...
|
def shutdown(): ...
|
||||||
|
|
||||||
|
@ -563,11 +589,13 @@ Module-Level Functions
|
||||||
|
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
==============
|
||||||
|
|
||||||
The reference implementation is Vinay Sajip's logging module [6].
|
The reference implementation is Vinay Sajip's logging module [6]_.
|
||||||
|
|
||||||
|
|
||||||
Packaging
|
Packaging
|
||||||
|
=========
|
||||||
|
|
||||||
The reference implementation is implemented as a single module.
|
The reference implementation is implemented as a single module.
|
||||||
This offers the simplest interface - all users have to do is
|
This offers the simplest interface - all users have to do is
|
||||||
|
@ -576,33 +604,35 @@ Packaging
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
[1] java.util.logging
|
.. [1] java.util.logging
|
||||||
http://java.sun.com/j2se/1.4/docs/guide/util/logging/
|
http://java.sun.com/j2se/1.4/docs/guide/util/logging/
|
||||||
|
|
||||||
[2] log4j: a Java logging package
|
.. [2] log4j: a Java logging package
|
||||||
http://jakarta.apache.org/log4j/docs/index.html
|
http://jakarta.apache.org/log4j/docs/index.html
|
||||||
|
|
||||||
[3] Protomatter's Syslog
|
.. [3] Protomatter's Syslog
|
||||||
http://protomatter.sourceforge.net/1.1.6/index.html
|
http://protomatter.sourceforge.net/1.1.6/index.html
|
||||||
http://protomatter.sourceforge.net/1.1.6/javadoc/com/protomatter/syslog/syslog-whitepaper.html
|
http://protomatter.sourceforge.net/1.1.6/javadoc/com/protomatter/syslog/syslog-whitepaper.html
|
||||||
|
|
||||||
[4] MAL mentions his mx.Log logging module:
|
.. [4] MAL mentions his mx.Log logging module:
|
||||||
https://mail.python.org/pipermail/python-dev/2002-February/019767.html
|
https://mail.python.org/pipermail/python-dev/2002-February/019767.html
|
||||||
|
|
||||||
[5] Jeff Bauer's Mr. Creosote
|
.. [5] Jeff Bauer's Mr. Creosote
|
||||||
http://starship.python.net/crew/jbauer/creosote/
|
http://starship.python.net/crew/jbauer/creosote/
|
||||||
|
|
||||||
[6] Vinay Sajip's logging module.
|
.. [6] Vinay Sajip's logging module.
|
||||||
http://www.red-dove.com/python_logging.html
|
http://www.red-dove.com/python_logging.html
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
..
|
||||||
Local Variables:
|
Local Variables:
|
||||||
mode: indented-text
|
mode: indented-text
|
||||||
indent-tabs-mode: nil
|
indent-tabs-mode: nil
|
||||||
|
|
Loading…
Reference in New Issue