mirror of
https://github.com/python/cpython
synced 2024-10-14 19:36:40 +00:00
[docs] Update logging cookbook with recipe for using a logger like an output… (GH-97730)
This commit is contained in:
parent
e8165d47b8
commit
cac2e8a51f
|
@ -3428,6 +3428,82 @@ the above handler, you'd pass structured data using something like this::
|
|||
i = 1
|
||||
logger.debug('Message %d', i, extra=extra)
|
||||
|
||||
How to treat a logger like an output stream
|
||||
-------------------------------------------
|
||||
|
||||
Sometimes, you need to interface to a third-party API which expects a file-like
|
||||
object to write to, but you want to direct the API's output to a logger. You
|
||||
can do this using a class which wraps a logger with a file-like API.
|
||||
Here's a short script illustrating such a class:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import logging
|
||||
|
||||
class LoggerWriter:
|
||||
def __init__(self, logger, level):
|
||||
self.logger = logger
|
||||
self.level = level
|
||||
|
||||
def write(self, message):
|
||||
if message != '\n': # avoid printing bare newlines, if you like
|
||||
self.logger.log(self.level, message)
|
||||
|
||||
def flush(self):
|
||||
# doesn't actually do anything, but might be expected of a file-like
|
||||
# object - so optional depending on your situation
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
# doesn't actually do anything, but might be expected of a file-like
|
||||
# object - so optional depending on your situation. You might want
|
||||
# to set a flag so that later calls to write raise an exception
|
||||
pass
|
||||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logger = logging.getLogger('demo')
|
||||
info_fp = LoggerWriter(logger, logging.INFO)
|
||||
debug_fp = LoggerWriter(logger, logging.DEBUG)
|
||||
print('An INFO message', file=info_fp)
|
||||
print('A DEBUG message', file=debug_fp)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
When this script is run, it prints
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
INFO:demo:An INFO message
|
||||
DEBUG:demo:A DEBUG message
|
||||
|
||||
You could also use ``LoggerWriter`` to redirect ``sys.stdout`` and
|
||||
``sys.stderr`` by doing something like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
|
||||
sys.stdout = LoggerWriter(logger, logging.INFO)
|
||||
sys.stderr = LoggerWriter(logger, logging.WARNING)
|
||||
|
||||
You should do this *after* configuring logging for your needs. In the above
|
||||
example, the :func:`~logging.basicConfig` call does this (using the
|
||||
``sys.stderr`` value *before* it is overwritten by a ``LoggerWriter``
|
||||
instance). Then, you'd get this kind of result:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print('Foo')
|
||||
INFO:demo:Foo
|
||||
>>> print('Bar', file=sys.stderr)
|
||||
WARNING:demo:Bar
|
||||
>>>
|
||||
|
||||
Of course, these above examples show output according to the format used by
|
||||
:func:`~logging.basicConfig`, but you can use a different formatter when you
|
||||
configure logging.
|
||||
|
||||
.. patterns-to-avoid:
|
||||
|
||||
|
|
Loading…
Reference in a new issue