Skip to content

Commit 3f040bc

Browse files
[3.10] [doc] Improve logging cookbook example. (GH-98481) (GH-98482)
Co-authored-by: Vinay Sajip <vinay_sajip@yahoo.co.uk>
1 parent dddbbd9 commit 3f040bc

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

Doc/howto/logging-cookbook.rst

+65
Original file line numberDiff line numberDiff line change
@@ -3712,6 +3712,71 @@ Of course, these above examples show output according to the format used by
37123712
:func:`~logging.basicConfig`, but you can use a different formatter when you
37133713
configure logging.
37143714

3715+
Note that with the above scheme, you are somewhat at the mercy of buffering and
3716+
the sequence of write calls which you are intercepting. For example, with the
3717+
definition of ``LoggerWriter`` above, if you have the snippet
3718+
3719+
.. code-block:: python
3720+
3721+
sys.stderr = LoggerWriter(logger, logging.WARNING)
3722+
1 / 0
3723+
3724+
then running the script results in
3725+
3726+
.. code-block:: text
3727+
3728+
WARNING:demo:Traceback (most recent call last):
3729+
3730+
WARNING:demo: File "/home/runner/cookbook-loggerwriter/test.py", line 53, in <module>
3731+
3732+
WARNING:demo:
3733+
WARNING:demo:main()
3734+
WARNING:demo: File "/home/runner/cookbook-loggerwriter/test.py", line 49, in main
3735+
3736+
WARNING:demo:
3737+
WARNING:demo:1 / 0
3738+
WARNING:demo:ZeroDivisionError
3739+
WARNING:demo::
3740+
WARNING:demo:division by zero
3741+
3742+
As you can see, this output isn't ideal. That's because the underlying code
3743+
which writes to ``sys.stderr`` makes mutiple writes, each of which results in a
3744+
separate logged line (for example, the last three lines above). To get around
3745+
this problem, you need to buffer things and only output log lines when newlines
3746+
are seen. Let's use a slghtly better implementation of ``LoggerWriter``:
3747+
3748+
.. code-block:: python
3749+
3750+
class BufferingLoggerWriter(LoggerWriter):
3751+
def __init__(self, logger, level):
3752+
super().__init__(logger, level)
3753+
self.buffer = ''
3754+
3755+
def write(self, message):
3756+
if '\n' not in message:
3757+
self.buffer += message
3758+
else:
3759+
parts = message.split('\n')
3760+
if self.buffer:
3761+
s = self.buffer + parts.pop(0)
3762+
self.logger.log(self.level, s)
3763+
self.buffer = parts.pop()
3764+
for part in parts:
3765+
self.logger.log(self.level, part)
3766+
3767+
This just buffers up stuff until a newline is seen, and then logs complete
3768+
lines. With this approach, you get better output:
3769+
3770+
.. code-block:: text
3771+
3772+
WARNING:demo:Traceback (most recent call last):
3773+
WARNING:demo: File "/home/runner/cookbook-loggerwriter/main.py", line 55, in <module>
3774+
WARNING:demo: main()
3775+
WARNING:demo: File "/home/runner/cookbook-loggerwriter/main.py", line 52, in main
3776+
WARNING:demo: 1/0
3777+
WARNING:demo:ZeroDivisionError: division by zero
3778+
3779+
37153780
.. patterns-to-avoid:
37163781
37173782
Patterns to avoid

0 commit comments

Comments
 (0)