Reformat according to PEP 12.
This commit is contained in:
parent
00888ff3be
commit
1842cd2321
512
pep-0391.txt
512
pep-0391.txt
|
@ -14,195 +14,211 @@ Post-History:
|
||||||
Abstract
|
Abstract
|
||||||
========
|
========
|
||||||
|
|
||||||
This PEP describes a new way of configuring logging using a dictionary to hold
|
This PEP describes a new way of configuring logging using a dictionary
|
||||||
configuration information.
|
to hold configuration information.
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
=========
|
=========
|
||||||
|
|
||||||
The present means for configuring Python's logging package is either by using
|
The present means for configuring Python's logging package is either
|
||||||
the logging API to configure logging programmatically, or else by means of
|
by using the logging API to configure logging programmatically, or
|
||||||
ConfigParser-based configuration files.
|
else by means of ConfigParser-based configuration files.
|
||||||
|
|
||||||
Programmatic configuration, while offering maximal control, fixes the
|
Programmatic configuration, while offering maximal control, fixes the
|
||||||
configuration in Python code. This does not facilitate changing it easily at
|
configuration in Python code. This does not facilitate changing it
|
||||||
runtime, and, as a result, the ability to flexibly turn the verbosity of
|
easily at runtime, and, as a result, the ability to flexibly turn the
|
||||||
logging up and down for different parts of a using application is lost. This
|
verbosity of logging up and down for different parts of a using
|
||||||
limits the usability of logging as an aid to diagnosing problems - and
|
application is lost. This limits the usability of logging as an aid
|
||||||
sometimes, logging is the only diagnostic aid available in production
|
to diagnosing problems - and sometimes, logging is the only diagnostic
|
||||||
environments.
|
aid available in production environments.
|
||||||
|
|
||||||
The ConfigParser-based configuration system is usable, but does not allow its
|
The ConfigParser-based configuration system is usable, but does not
|
||||||
users to configure all aspects of the logging package. For example, Filters
|
allow its users to configure all aspects of the logging package. For
|
||||||
cannot be configured using this system. Furthermore, the ConfigParser format
|
example, Filters cannot be configured using this system. Furthermore,
|
||||||
appears to engender dislike (sometimes strong dislike) in some quarters.
|
the ConfigParser format appears to engender dislike (sometimes strong
|
||||||
Though it was chosen because it was the only configuration format supported in
|
dislike) in some quarters. Though it was chosen because it was the
|
||||||
the Python standard at that time, many people regard it (or perhaps just the
|
only configuration format supported in the Python standard at that
|
||||||
particular schema chosen for logging's configuration) as 'crufty' or 'ugly',
|
time, many people regard it (or perhaps just the particular schema
|
||||||
in some cases apparently on purely aesthetic grounds.
|
chosen for logging's configuration) as 'crufty' or 'ugly', in some
|
||||||
|
cases apparently on purely aesthetic grounds.
|
||||||
|
|
||||||
Recent versions of Python inlude JSON support in the standard library, and
|
Recent versions of Python include JSON support in the standard
|
||||||
this is also usable as a configuration format. In other environments, such as
|
library, and this is also usable as a configuration format. In other
|
||||||
Google App Engine, YAML is used to configure applications, and usually the
|
environments, such as Google App Engine, YAML is used to configure
|
||||||
configuration of logging would be considered an integral part of the
|
applications, and usually the configuration of logging would be
|
||||||
application configuration. Although the standard library does not contain
|
considered an integral part of the application configuration.
|
||||||
YAML support at present, support for both JSON and YAML can be provided in a
|
Although the standard library does not contain YAML support at
|
||||||
common way because both of these serialization formats allow deserialization
|
present, support for both JSON and YAML can be provided in a common
|
||||||
|
way because both of these serialization formats allow deserialization
|
||||||
of Python dictionaries.
|
of Python dictionaries.
|
||||||
|
|
||||||
By providing a way to configure logging by passing the configuration in a
|
By providing a way to configure logging by passing the configuration
|
||||||
dictionary, logging will be easier to configure not only for users of JSON
|
in a dictionary, logging will be easier to configure not only for
|
||||||
and/or YAML, but also for users of bespoke configuration methods, by providing
|
users of JSON and/or YAML, but also for users of bespoke configuration
|
||||||
a common format in which to describe the desired configuration.
|
methods, by providing a common format in which to describe the desired
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
Another drawback of the current ConfigParser-based configuration
|
||||||
|
system is that it does not support incremental configuration: a new
|
||||||
|
configuration completely replaces the existing configuration.
|
||||||
|
Although full flexibility for incremental configuration is difficult
|
||||||
|
to provide in a multi-threaded environment, the new configuration
|
||||||
|
mechanism will allow the provision of limited support for incremental
|
||||||
|
configuration.
|
||||||
|
|
||||||
Another drawback of the current ConfigParser-based configuration system is
|
|
||||||
that it does not support incremental configuration: a new configuration
|
|
||||||
completely replaces the existing configuration. Although full flexibility for
|
|
||||||
incremental configuration is difficult to provide in a multi-threaded
|
|
||||||
environment, the new configuration mechanism will allow the provision of
|
|
||||||
limited support for incremental configuration.
|
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
=============
|
=============
|
||||||
|
|
||||||
The specification consists of two parts: the API and the format of the
|
The specification consists of two parts: the API and the format of the
|
||||||
dictionary used to convey configuration information (i.e. the schema to which
|
dictionary used to convey configuration information (i.e. the schema
|
||||||
it must conform).
|
to which it must conform).
|
||||||
|
|
||||||
|
|
||||||
Naming
|
Naming
|
||||||
------
|
------
|
||||||
|
|
||||||
Historically, the logging package has not been PEP-8 conformant. At some
|
Historically, the logging package has not been PEP 8 conformant [1]_.
|
||||||
future time, this will be corrected by changing method and function names in
|
At some future time, this will be corrected by changing method and
|
||||||
the package in order to conform with PEP-8. However, in the interests of
|
function names in the package in order to conform with PEP 8.
|
||||||
uniformity, the proposed additions to the API use a naming scheme which is
|
However, in the interests of uniformity, the proposed additions to the
|
||||||
consistent with the present scheme used by logging.
|
API use a naming scheme which is consistent with the present scheme
|
||||||
|
used by logging.
|
||||||
|
|
||||||
|
|
||||||
API
|
API
|
||||||
---
|
---
|
||||||
|
|
||||||
The logging.config module will have the following additions:
|
The logging.config module will have the following additions:
|
||||||
|
|
||||||
* A class, called ``DictConfigurator``, whose constructor is passed the
|
* A class, called ``DictConfigurator``, whose constructor is passed
|
||||||
dictionary used for configuration, and which has a ``configure()`` method.
|
the dictionary used for configuration, and which has a
|
||||||
|
``configure()`` method.
|
||||||
|
|
||||||
* A callable, called ``dictConfigClass``, which will (by default) be set to
|
* A callable, called ``dictConfigClass``, which will (by default) be
|
||||||
``DictConfigurator``. This is provided so that if desired,
|
set to ``DictConfigurator``. This is provided so that if desired,
|
||||||
``DictConfigurator`` can be replaced with a suitable user-defined
|
``DictConfigurator`` can be replaced with a suitable user-defined
|
||||||
implementation.
|
implementation.
|
||||||
|
|
||||||
* A function, called ``dictConfig()``, which takes a single argument - the
|
* A function, called ``dictConfig()``, which takes a single argument
|
||||||
dictionary holding the configuration. This function will call
|
- the dictionary holding the configuration. This function will
|
||||||
``dictConfigClass`` passing the specified dictionary, and then call the
|
call ``dictConfigClass`` passing the specified dictionary, and then
|
||||||
``configure()`` method on the returned object to actually put the
|
call the ``configure()`` method on the returned object to actually
|
||||||
configuration into effect::
|
put the configuration into effect::
|
||||||
|
|
||||||
|
def dictConfig(config):
|
||||||
|
dictConfigClass(config).configure()
|
||||||
|
|
||||||
def dictConfig(config):
|
|
||||||
dictConfigClass(config).configure()
|
|
||||||
|
|
||||||
Dictionary Schema - Overview
|
Dictionary Schema - Overview
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
Before describing the schema in detail, it is worth saying a few words about
|
Before describing the schema in detail, it is worth saying a few words
|
||||||
object connections, support for user-defined objects and access to external
|
about object connections, support for user-defined objects and access
|
||||||
objects.
|
to external objects.
|
||||||
|
|
||||||
|
|
||||||
Object connections
|
Object connections
|
||||||
''''''''''''''''''
|
''''''''''''''''''
|
||||||
|
|
||||||
The schema is intended to describe a set of logging objects - loggers,
|
The schema is intended to describe a set of logging objects - loggers,
|
||||||
handlers, formatters, filters - which are connected to each other in an
|
handlers, formatters, filters - which are connected to each other in
|
||||||
object graph. Thus, the schema needs to represent connections between the
|
an object graph. Thus, the schema needs to represent connections
|
||||||
objects. For example, say that, once configured, a particular logger has an
|
between the objects. For example, say that, once configured, a
|
||||||
attached to it a particular handler. For the purposes of this discussion,
|
particular logger has an attached to it a particular handler. For the
|
||||||
we can say that the logger represents the source, and the handler the
|
purposes of this discussion, we can say that the logger represents the
|
||||||
destination, of a connection between the two. Of course in the configured
|
source, and the handler the destination, of a connection between the
|
||||||
objects this is represented by the logger holding a reference to the
|
two. Of course in the configured objects this is represented by the
|
||||||
handler. In the configuration dict, this is done by giving each destination
|
logger holding a reference to the handler. In the configuration dict,
|
||||||
object an id which identifies it unambiguously, and then using the id in the
|
this is done by giving each destination object an id which identifies
|
||||||
source object's configuration to indicate that a connection exists between
|
it unambiguously, and then using the id in the source object's
|
||||||
the source and the destination object with that id.
|
configuration to indicate that a connection exists between the source
|
||||||
|
and the destination object with that id.
|
||||||
|
|
||||||
So, for example, consider the following YAML snippet::
|
So, for example, consider the following YAML snippet::
|
||||||
|
|
||||||
handlers:
|
handlers:
|
||||||
h1: #This is an id
|
h1: #This is an id
|
||||||
# configuration of handler with id h1 goes here
|
# configuration of handler with id h1 goes here
|
||||||
h2: #This is another id
|
h2: #This is another id
|
||||||
# configuration of handler with id h2 goes here
|
# configuration of handler with id h2 goes here
|
||||||
loggers:
|
loggers:
|
||||||
foo.bar.baz:
|
foo.bar.baz:
|
||||||
# other configuration for logger "foo.bar.baz"
|
# other configuration for logger "foo.bar.baz"
|
||||||
handlers: [h1, h2]
|
handlers: [h1, h2]
|
||||||
|
|
||||||
(Note: YAML will be used in this document as it is more readable than the
|
(Note: YAML will be used in this document as it is more readable than
|
||||||
equivalent Python source form for the dictionary.)
|
the equivalent Python source form for the dictionary.)
|
||||||
|
|
||||||
The ids for loggers are the logger names which would be used
|
The ids for loggers are the logger names which would be used
|
||||||
programmatically to obtain a reference to those loggers, e.g.
|
programmatically to obtain a reference to those loggers, e.g.
|
||||||
``foo.bar.baz``. The ids for other objects can be any string value (such as
|
``foo.bar.baz``. The ids for other objects can be any string value
|
||||||
``h1``, ``h2`` above) and they are transient, in that they are only
|
(such as ``h1``, ``h2`` above) and they are transient, in that they
|
||||||
meaningful for processing the configuration dictionary and used to
|
are only meaningful for processing the configuration dictionary and
|
||||||
determine connections between objects, and are not persisted anywhere when
|
used to determine connections between objects, and are not persisted
|
||||||
the configuration call is complete.
|
anywhere when the configuration call is complete.
|
||||||
|
|
||||||
|
The above snippet indicates that logger named ``foo.bar.baz`` should
|
||||||
|
have two handlers attached to it, which are described by the handler
|
||||||
|
ids ``h1`` and ``h2``.
|
||||||
|
|
||||||
The above snippet indicates that logger named ``foo.bar.baz`` should have
|
|
||||||
two handlers attached to it, which are described by the handler ids ``h1``
|
|
||||||
and ``h2``.
|
|
||||||
|
|
||||||
User-defined objects
|
User-defined objects
|
||||||
''''''''''''''''''''
|
''''''''''''''''''''
|
||||||
|
|
||||||
The schema should support user-defined objects for handlers, filters and
|
The schema should support user-defined objects for handlers, filters
|
||||||
formatters. (Loggers do not need to have different types for different
|
and formatters. (Loggers do not need to have different types for
|
||||||
instances, so there is no support - in the configuration - for user-defined
|
different instances, so there is no support - in the configuration -
|
||||||
logger classes.)
|
for user-defined logger classes.)
|
||||||
|
|
||||||
Objects to be configured will typically be described by dictionaries which
|
Objects to be configured will typically be described by dictionaries
|
||||||
detail their configuration. In some places, the logging system will be able
|
which detail their configuration. In some places, the logging system
|
||||||
to infer from the context how an object is to be instantiated, but when a
|
will be able to infer from the context how an object is to be
|
||||||
user-defined object is to be instantiated, the system will not know how to do
|
instantiated, but when a user-defined object is to be instantiated,
|
||||||
this. In order to provide complete flexibility for user-defined object
|
the system will not know how to do this. In order to provide complete
|
||||||
instantiation, the user will need to provide a 'factory' - a callable which
|
flexibility for user-defined object instantiation, the user will need
|
||||||
is called with a configuration dictionary and which returns the instantiated
|
to provide a 'factory' - a callable which is called with a
|
||||||
object. This will be signalled by the factory being made available under
|
configuration dictionary and which returns the instantiated object.
|
||||||
the special key ``'()'``. Here's a concrete example::
|
This will be signalled by the factory being made available under the
|
||||||
|
special key ``'()'``. Here's a concrete example::
|
||||||
|
|
||||||
formatters:
|
formatters:
|
||||||
brief:
|
brief:
|
||||||
format: '%(message)s'
|
format: '%(message)s'
|
||||||
default:
|
default:
|
||||||
format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
|
format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
|
||||||
datefmt: '%Y-%m-%d %H:%M:%S'
|
datefmt: '%Y-%m-%d %H:%M:%S'
|
||||||
custom:
|
custom:
|
||||||
(): my.package.customFormatterFactory
|
(): my.package.customFormatterFactory
|
||||||
bar: baz
|
bar: baz
|
||||||
spam: 99.9
|
spam: 99.9
|
||||||
answer: 42
|
answer: 42
|
||||||
|
|
||||||
The above YAML snippet defines three formatters. The first, with id
|
The above YAML snippet defines three formatters. The first, with id
|
||||||
``brief``, is a standard ``logging.Formatter`` instance with the
|
``brief``, is a standard ``logging.Formatter`` instance with the
|
||||||
specified format string. The second, with id ``default``, has a longer
|
specified format string. The second, with id ``default``, has a
|
||||||
format and also defines the time format explicitly, and will result in a
|
longer format and also defines the time format explicitly, and will
|
||||||
``logging.Formatter`` initialized with those two format strings. Shown in
|
result in a ``logging.Formatter`` initialized with those two format
|
||||||
Python source form, the ``brief`` and ``default`` formatters have
|
strings. Shown in Python source form, the ``brief`` and ``default``
|
||||||
have configuration sub-dictionaries::
|
formatters have configuration sub-dictionaries::
|
||||||
|
|
||||||
{
|
{
|
||||||
'format' : '%(message)s'
|
'format' : '%(message)s'
|
||||||
}
|
}
|
||||||
|
|
||||||
and::
|
and::
|
||||||
|
|
||||||
{
|
{
|
||||||
'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
|
'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
|
||||||
'datefmt' : '%Y-%m-%d %H:%M:%S'
|
'datefmt' : '%Y-%m-%d %H:%M:%S'
|
||||||
}
|
}
|
||||||
|
|
||||||
respectively, and as these dictionaries do not contain the special key
|
respectively, and as these dictionaries do not contain the special key
|
||||||
``'()'``, the instantiation is inferred from the context: as a result,
|
``'()'``, the instantiation is inferred from the context: as a result,
|
||||||
standard ``logging.Formatter`` instances are created. The configuration
|
standard ``logging.Formatter`` instances are created. The
|
||||||
sub-dictionary for the third formatter, with id ``custom``, is::
|
configuration sub-dictionary for the third formatter, with id
|
||||||
|
``custom``, is::
|
||||||
|
|
||||||
{
|
{
|
||||||
'()' : 'my.package.customFormatterFactory',
|
'()' : 'my.package.customFormatterFactory',
|
||||||
|
@ -211,118 +227,128 @@ sub-dictionary for the third formatter, with id ``custom``, is::
|
||||||
'answer' : 42
|
'answer' : 42
|
||||||
}
|
}
|
||||||
|
|
||||||
and this contains the special key ``'()'``, which means that user-defined
|
and this contains the special key ``'()'``, which means that
|
||||||
instantiation is wanted. In this case, the specified factory callable will be
|
user-defined instantiation is wanted. In this case, the specified
|
||||||
located using normal import mechanisms and called with the *remaining* items
|
factory callable will be located using normal import mechanisms and
|
||||||
in the configuration sub-dictionary as keyword arguments. In the above
|
called with the *remaining* items in the configuration sub-dictionary
|
||||||
example, the formatter with id ``custom`` will be assumed to be returned by
|
as keyword arguments. In the above example, the formatter with id
|
||||||
the call::
|
``custom`` will be assumed to be returned by the call::
|
||||||
|
|
||||||
my.package.customFormatterFactory(bar="baz", spam=99.9, answer=42)
|
my.package.customFormatterFactory(bar="baz", spam=99.9, answer=42)
|
||||||
|
|
||||||
|
The key ``'()'`` has been used as the special key because it is not a
|
||||||
|
valid keyword parameter name, and so will not clash with the names of
|
||||||
|
the keyword arguments used in the call. The ``'()'`` also serves as a
|
||||||
|
mnemonic that the corresponding value is a callable.
|
||||||
|
|
||||||
The key ``'()'`` has been used as the special key because it is not a valid
|
|
||||||
keyword parameter name, and so will not clash with the names of the keyword
|
|
||||||
arguments used in the call. The ``'()'`` also serves as a mnemonic that the
|
|
||||||
corresponding value is a callable.
|
|
||||||
|
|
||||||
Access to external objects
|
Access to external objects
|
||||||
''''''''''''''''''''''''''
|
''''''''''''''''''''''''''
|
||||||
|
|
||||||
There are times where a configuration will need to refer to objects external
|
There are times where a configuration will need to refer to objects
|
||||||
to the configuration, for example ``sys.stderr``. If the configuration dict
|
external to the configuration, for example ``sys.stderr``. If the
|
||||||
is constructed using Python code then this is straightforward, but a problem
|
configuration dict is constructed using Python code then this is
|
||||||
arises when the configuration is provided via a text file (e.g. JSON, YAML).
|
straightforward, but a problem arises when the configuration is
|
||||||
In a text file, there is no standard way to distinguish ``sys.stderr`` from
|
provided via a text file (e.g. JSON, YAML). In a text file, there is
|
||||||
the literal string ``'sys.stderr'``. To facilitate this distinction, the
|
no standard way to distinguish ``sys.stderr`` from the literal string
|
||||||
configuration system will look for certain special prefixes in string values
|
``'sys.stderr'``. To facilitate this distinction, the configuration
|
||||||
and treat them specially. For example, if the literal string
|
system will look for certain special prefixes in string values and
|
||||||
``'ext://sys.stderr'`` is provided as a value in the configuration, then the
|
treat them specially. For example, if the literal string
|
||||||
``ext://`` will be stripped off and the remainder of the value processed using
|
``'ext://sys.stderr'`` is provided as a value in the configuration,
|
||||||
normal import mechanisms.
|
then the ``ext://`` will be stripped off and the remainder of the
|
||||||
|
value processed using normal import mechanisms.
|
||||||
|
|
||||||
The handling of such prefixes will be done in a way analogous to protocol
|
The handling of such prefixes will be done in a way analogous to
|
||||||
handling: there will be a generic mechanism to look for prefixes which match
|
protocol handling: there will be a generic mechanism to look for
|
||||||
the regular expression ``^(?P<prefix>[a-z]+)://(?P<suffix>.*)$`` whereby, if
|
prefixes which match the regular expression
|
||||||
the ``prefix`` is recognised, the ``suffix`` is processed in a
|
``^(?P<prefix>[a-z]+)://(?P<suffix>.*)$`` whereby, if the ``prefix``
|
||||||
prefix-dependent manner and the result of the processing replaces the string
|
is recognised, the ``suffix`` is processed in a prefix-dependent
|
||||||
value. If the prefix is not recognised, then the string value will be left
|
manner and the result of the processing replaces the string value. If
|
||||||
|
the prefix is not recognised, then the string value will be left
|
||||||
as-is.
|
as-is.
|
||||||
|
|
||||||
The implementation will provide for a set of standard prefixes such as
|
The implementation will provide for a set of standard prefixes such as
|
||||||
``ext://`` but it will be possible to disable the mechanism completely or
|
``ext://`` but it will be possible to disable the mechanism completely
|
||||||
provide additional or different prefixes for special handling.
|
or provide additional or different prefixes for special handling.
|
||||||
|
|
||||||
|
|
||||||
Dictionary Schema - Detail
|
Dictionary Schema - Detail
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
The dictionary passed to ``dictConfig()`` must contain the following keys:
|
The dictionary passed to ``dictConfig()`` must contain the following
|
||||||
|
keys:
|
||||||
|
|
||||||
* `version` - to be set to an integer value representing the schema
|
* `version` - to be set to an integer value representing the schema
|
||||||
version. The only valid value at present is 1, but having this key allows
|
version. The only valid value at present is 1, but having this key
|
||||||
the schema to evolve while still preserving backwards compatibility.
|
allows the schema to evolve while still preserving backwards
|
||||||
|
compatibility.
|
||||||
|
|
||||||
All other keys are optional, but if present they will be interpreted as described
|
All other keys are optional, but if present they will be interpreted
|
||||||
below. In all cases below where a 'configuring dict' is mentioned, it will be
|
as described below. In all cases below where a 'configuring dict' is
|
||||||
checked for the special ``'()'`` key to see if a custom instantiation is
|
mentioned, it will be checked for the special ``'()'`` key to see if a
|
||||||
required. If so, the mechanism described above is used to instantiate;
|
custom instantiation is required. If so, the mechanism described
|
||||||
otherwise, the context is used to determine how to instantiate.
|
above is used to instantiate; otherwise, the context is used to
|
||||||
|
determine how to instantiate.
|
||||||
|
|
||||||
* `formatters` - the corresponding value will be a dict in which each key is
|
* `formatters` - the corresponding value will be a dict in which each
|
||||||
a formatter id and each value is a dict describing how to configure the
|
key is a formatter id and each value is a dict describing how to
|
||||||
corresponding Formatter instance.
|
configure the corresponding Formatter instance.
|
||||||
|
|
||||||
The configuring dict is searched for keys ``format`` and ``datefmt`` (with
|
The configuring dict is searched for keys ``format`` and ``datefmt``
|
||||||
defaults of ``None``) and these are used to construct a
|
(with defaults of ``None``) and these are used to construct a
|
||||||
``logging.Formatter`` instance.
|
``logging.Formatter`` instance.
|
||||||
|
|
||||||
* `filters` - the corresponding value will be a dict in which each key is
|
* `filters` - the corresponding value will be a dict in which each key
|
||||||
a filter id and each value is a dict describing how to configure the
|
is a filter id and each value is a dict describing how to configure
|
||||||
corresponding Filter instance.
|
the corresponding Filter instance.
|
||||||
|
|
||||||
The configuring dict is searched for key ``name`` (defaulting to the empty
|
The configuring dict is searched for key ``name`` (defaulting to the
|
||||||
string) and this is used to construct a ``logging.Filter`` instance.
|
empty string) and this is used to construct a ``logging.Filter``
|
||||||
|
instance.
|
||||||
|
|
||||||
* `handlers` - the corresponding value will be a dict in which each key is
|
* `handlers` - the corresponding value will be a dict in which each
|
||||||
a handler id and each value is a dict describing how to configure the
|
key is a handler id and each value is a dict describing how to
|
||||||
corresponding Handler instance.
|
configure the corresponding Handler instance.
|
||||||
|
|
||||||
The configuring dict is searched for the following keys:
|
The configuring dict is searched for the following keys:
|
||||||
|
|
||||||
* ``class`` (mandatory). This is the fully qualified name of the handler
|
* ``class`` (mandatory). This is the fully qualified name of the
|
||||||
class.
|
handler class.
|
||||||
|
|
||||||
* ``level`` (optional). The level of the handler.
|
* ``level`` (optional). The level of the handler.
|
||||||
|
|
||||||
* ``formatter`` (optional). The id of the formatter for this handler.
|
* ``formatter`` (optional). The id of the formatter for this
|
||||||
|
handler.
|
||||||
|
|
||||||
* ``filters`` (optional). A list of ids of the filters for this handler.
|
* ``filters`` (optional). A list of ids of the filters for this
|
||||||
|
handler.
|
||||||
|
|
||||||
All *other* keys are passed through as keyword arguments to the handler's
|
All *other* keys are passed through as keyword arguments to the
|
||||||
constructor. For example, given the snippet::
|
handler's constructor. For example, given the snippet::
|
||||||
|
|
||||||
handlers:
|
handlers:
|
||||||
console:
|
console:
|
||||||
class : logging.StreamHandler
|
class : logging.StreamHandler
|
||||||
formatter: brief
|
formatter: brief
|
||||||
level : INFO
|
level : INFO
|
||||||
filters: [allow_foo]
|
filters: [allow_foo]
|
||||||
stream : ext://sys.stdout
|
stream : ext://sys.stdout
|
||||||
file:
|
file:
|
||||||
class : logging.handlers.RotatingFileHandler
|
class : logging.handlers.RotatingFileHandler
|
||||||
formatter: precise
|
formatter: precise
|
||||||
filename: logconfig.log
|
filename: logconfig.log
|
||||||
maxBytes: 1024
|
maxBytes: 1024
|
||||||
backupCount: 3
|
backupCount: 3
|
||||||
|
|
||||||
the handler with id ``console`` is instantiated as a
|
the handler with id ``console`` is instantiated as a
|
||||||
``logging.StreamHandler``, using ``sys.stdout`` as the underlying stream.
|
``logging.StreamHandler``, using ``sys.stdout`` as the underlying
|
||||||
The handler with id ``file`` is instantiated as a
|
stream. The handler with id ``file`` is instantiated as a
|
||||||
``logging.handlers.RotatingFileHandler`` with the keyword arguments
|
``logging.handlers.RotatingFileHandler`` with the keyword arguments
|
||||||
``filename="logconfig.log", maxBytes=1024, backupCount=3``.
|
``filename="logconfig.log", maxBytes=1024, backupCount=3``.
|
||||||
|
|
||||||
* `loggers` - the corresponding value will be a dict in which each key is
|
* `loggers` - the corresponding value will be a dict in which each key
|
||||||
a logger name and each value is a dict describing how to configure the
|
is a logger name and each value is a dict describing how to
|
||||||
corresponding Logger instance.
|
configure the corresponding Logger instance.
|
||||||
|
|
||||||
The configuring dict is searched for the following keys:
|
The configuring dict is searched for the following keys:
|
||||||
|
|
||||||
|
@ -330,31 +356,34 @@ otherwise, the context is used to determine how to instantiate.
|
||||||
|
|
||||||
* ``propagate`` (optional). The propagation setting of the logger.
|
* ``propagate`` (optional). The propagation setting of the logger.
|
||||||
|
|
||||||
* ``filters`` (optional). A list of ids of the filters for this logger.
|
* ``filters`` (optional). A list of ids of the filters for this
|
||||||
|
logger.
|
||||||
|
|
||||||
* ``handlers`` (optional). A list of ids of the handlers for this logger.
|
* ``handlers`` (optional). A list of ids of the handlers for this
|
||||||
|
logger.
|
||||||
|
|
||||||
The specified loggers will be configured according to the level,
|
The specified loggers will be configured according to the level,
|
||||||
propagation, filters and handlers specified.
|
propagation, filters and handlers specified.
|
||||||
|
|
||||||
* `root` - this will be the configuration for the root logger. Processing of
|
* `root` - this will be the configuration for the root logger.
|
||||||
the configuration will be as for any logger, except that the ``propagate``
|
Processing of the configuration will be as for any logger, except
|
||||||
setting will not be applicable.
|
that the ``propagate`` setting will not be applicable.
|
||||||
|
|
||||||
* `incremental` - whether the configuration is to be interpreted as
|
* `incremental` - whether the configuration is to be interpreted as
|
||||||
incremental to the existing configuration. This value defaults to False,
|
incremental to the existing configuration. This value defaults to
|
||||||
which means that the specified configuration replaces the existing
|
``False``, which means that the specified configuration replaces the
|
||||||
configuration with the same semantics as used by the existing
|
existing configuration with the same semantics as used by the
|
||||||
``fileConfig()`` API.
|
existing ``fileConfig()`` API.
|
||||||
|
|
||||||
|
If the specified value is ``True``, the configuration is processed
|
||||||
|
as described in the section on `Incremental Configuration`_, below.
|
||||||
|
|
||||||
If the specified value is True, the configuration is processed as described
|
|
||||||
in the section on "Incremental Configuration", below.
|
|
||||||
|
|
||||||
A Working Example
|
A Working Example
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The following is an actual working configuration in YAML format (except that
|
The following is an actual working configuration in YAML format
|
||||||
the email addresses are bogus)::
|
(except that the email addresses are bogus)::
|
||||||
|
|
||||||
formatters:
|
formatters:
|
||||||
brief:
|
brief:
|
||||||
|
@ -404,45 +433,57 @@ the email addresses are bogus)::
|
||||||
level : DEBUG
|
level : DEBUG
|
||||||
handlers : [console, file]
|
handlers : [console, file]
|
||||||
|
|
||||||
|
|
||||||
Incremental Configuration
|
Incremental Configuration
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
It is difficult to provide complete flexibility for incremental configuration.
|
It is difficult to provide complete flexibility for incremental
|
||||||
For example, because objects such as handlers, filters and formatters are
|
configuration. For example, because objects such as handlers, filters
|
||||||
anonymous, once a configuration is set up, it is not possible to refer to such
|
and formatters are anonymous, once a configuration is set up, it is
|
||||||
anonymous objects when augmenting a configuration. For example, if an initial
|
not possible to refer to such anonymous objects when augmenting a
|
||||||
call is made to configure the system where logger ``foo`` has a handler with
|
configuration. For example, if an initial call is made to configure
|
||||||
id ``console`` attached, then a subsequent call to configure a logger ``bar``
|
the system where logger ``foo`` has a handler with id ``console``
|
||||||
with id ``console`` would create a new handler instance, as the id ``console``
|
attached, then a subsequent call to configure a logger ``bar`` with id
|
||||||
|
``console`` would create a new handler instance, as the id ``console``
|
||||||
from the first call isn't kept.
|
from the first call isn't kept.
|
||||||
|
|
||||||
Furthermore, there is not a compelling case for arbitrarily altering the
|
Furthermore, there is not a compelling case for arbitrarily altering
|
||||||
object graph of loggers, handlers, filters, formatters at run-time, once a
|
the object graph of loggers, handlers, filters, formatters at
|
||||||
configuration is set up; the verbosity of loggers can be controlled just by
|
run-time, once a configuration is set up; the verbosity of loggers can
|
||||||
setting levels (and perhaps propagation flags).
|
be controlled just by setting levels (and perhaps propagation flags).
|
||||||
|
|
||||||
|
Thus, when the ``incremental`` key of a configuration dict is present
|
||||||
|
and is ``True``, the system will ignore the ``formatters``,
|
||||||
|
``filters``, ``handlers`` entries completely, and process only the
|
||||||
|
``level`` and ``propagate`` settings in the ``loggers`` and ``root``
|
||||||
|
entries.
|
||||||
|
|
||||||
Thus, when the ``incremental`` key of a configuration dict is present and
|
|
||||||
is ``True``, the system will ignore the ``formatters``, ``filters``,
|
|
||||||
``handlers`` entries completely, and process only the ``level`` and
|
|
||||||
``propagate`` settings in the ``loggers`` and ``root`` entries.
|
|
||||||
|
|
||||||
Configuration Errors
|
Configuration Errors
|
||||||
====================
|
====================
|
||||||
|
|
||||||
If an error is encountered during configuration, the system will raise a
|
If an error is encountered during configuration, the system will raise
|
||||||
``ValueError`` or a ``TypeError`` with a suitably descriptive message. The
|
a ``ValueError`` or a ``TypeError`` with a suitably descriptive
|
||||||
following is a (possibly incomplete) list of conditions which will raise an
|
message. The following is a (possibly incomplete) list of conditions
|
||||||
error:
|
which will raise an error:
|
||||||
|
|
||||||
* A ``level`` which is not a string or which is a string not corresponding to
|
* A ``level`` which is not a string or which is a string not
|
||||||
an actual logging level
|
corresponding to an actual logging level
|
||||||
|
|
||||||
* A ``propagate`` value which is not a Boolean
|
* A ``propagate`` value which is not a boolean
|
||||||
|
|
||||||
* An id which does not have a corresponding destination
|
* An id which does not have a corresponding destination
|
||||||
|
|
||||||
* An invalid logger name
|
* An invalid logger name
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [1] PEP 8, Style Guide for Python Code, van Rossum, Warsaw
|
||||||
|
(http://www.python.org/dev/peps/pep-0008)
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
@ -458,4 +499,3 @@ This document has been placed in the public domain.
|
||||||
fill-column: 70
|
fill-column: 70
|
||||||
coding: utf-8
|
coding: utf-8
|
||||||
End:
|
End:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue