|
|
|
@ -1694,6 +1694,9 @@ When the above script is run, it prints:: |
|
|
|
Note that the order of items might be different according to the version of |
|
|
|
Python used. |
|
|
|
|
|
|
|
|
|
|
|
.. _custom-handlers: |
|
|
|
|
|
|
|
.. currentmodule:: logging.config |
|
|
|
|
|
|
|
Customizing handlers with :func:`dictConfig` |
|
|
|
@ -1948,3 +1951,87 @@ handler. So the only slightly unusual thing which might trip you up is that the |
|
|
|
parentheses go around the format string and the arguments, not just the format |
|
|
|
string. That’s because the __ notation is just syntax sugar for a constructor |
|
|
|
call to one of the ``XXXMessage`` classes shown above. |
|
|
|
|
|
|
|
|
|
|
|
.. _filters-dictconfig: |
|
|
|
|
|
|
|
.. currentmodule:: logging.config |
|
|
|
|
|
|
|
Configuring filters with :func:`dictConfig` |
|
|
|
------------------------------------------- |
|
|
|
|
|
|
|
You *can* configure filters using :func:`~logging.config.dictConfig`, though it |
|
|
|
might not be obvious at first glance how to do it (hence this recipe). Since |
|
|
|
:class:`~logging.Filter` is the only filter class included in the standard |
|
|
|
library, and it is unlikely to cater to many requirements (it's only there as a |
|
|
|
base class), you will typically need to define your own :class:`~logging.Filter` |
|
|
|
subclass with an overridden :meth:`~logging.Filter.filter` method. To do this, |
|
|
|
specify the ``()`` key in the configuration dictionary for the filter, |
|
|
|
specifying a callable which will be used to create the filter (a class is the |
|
|
|
most obvious, but you can provide any callable which returns a |
|
|
|
:class:`~logging.Filter` instance). Here is a complete example:: |
|
|
|
|
|
|
|
import logging |
|
|
|
import logging.config |
|
|
|
import sys |
|
|
|
|
|
|
|
class MyFilter(logging.Filter): |
|
|
|
def __init__(self, param=None): |
|
|
|
self.param = param |
|
|
|
|
|
|
|
def filter(self, record): |
|
|
|
if self.param is None: |
|
|
|
allow = True |
|
|
|
else: |
|
|
|
allow = self.param not in record.msg |
|
|
|
if allow: |
|
|
|
record.msg = 'changed: ' + record.msg |
|
|
|
return allow |
|
|
|
|
|
|
|
LOGGING = { |
|
|
|
'version': 1, |
|
|
|
'filters': { |
|
|
|
'myfilter': { |
|
|
|
'()': MyFilter, |
|
|
|
'param': 'noshow', |
|
|
|
} |
|
|
|
}, |
|
|
|
'handlers': { |
|
|
|
'console': { |
|
|
|
'class': 'logging.StreamHandler', |
|
|
|
'filters': ['myfilter'] |
|
|
|
} |
|
|
|
}, |
|
|
|
'root': { |
|
|
|
'level': 'DEBUG', |
|
|
|
'handlers': ['console'] |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
logging.config.dictConfig(LOGGING) |
|
|
|
logging.debug('hello') |
|
|
|
logging.debug('hello - noshow') |
|
|
|
|
|
|
|
This example shows how you can pass configuration data to the callable which |
|
|
|
constructs the instance, in the form of keyword parameters. When run, the above |
|
|
|
script will print:: |
|
|
|
|
|
|
|
changed: hello |
|
|
|
|
|
|
|
which shows that the filter is working as configured. |
|
|
|
|
|
|
|
A couple of extra points to note: |
|
|
|
|
|
|
|
* If you can't refer to the callable directly in the configuration (e.g. if it |
|
|
|
lives in a different module, and you can't import it directly where the |
|
|
|
configuration dictionary is), you can use the form ``ext://...`` as described |
|
|
|
in :ref:`logging-config-dict-externalobj`. For example, you could have used |
|
|
|
the text ``'ext://__main__.MyFilter'`` instead of ``MyFilter`` in the above |
|
|
|
example. |
|
|
|
|
|
|
|
* As well as for filters, this technique can also be used to configure custom |
|
|
|
handlers and formatters. See :ref:`logging-config-dict-userdef` for more |
|
|
|
information on how logging supports using user-defined objects in its |
|
|
|
configuration, and see the other cookbook recipe :ref:`custom-handlers` above. |
|
|
|
|