[issue35530] Counter-intuitive logging API

Karthikeyan Singaravelan report at bugs.python.org
Wed Dec 19 07:01:33 EST 2018


Karthikeyan Singaravelan <tir.karthi at gmail.com> added the comment:

> If you have 3.8 installed, feel free to test the code yourself and report what happens.

I tested it on master and it's the same as per the original report.

➜  cpython git:(master) cat ../backups/bpo35530_1.py
import logging
logger = logging.getLogger(name='main')
logger.setLevel(logging.INFO)
logger.error('XXX')
logging.error('ZZZ')
logger.error('XXX')
➜  cpython git:(master) ./python.exe
Python 3.8.0a0 (heads/master:1dd035954b, Dec 18 2018, 10:12:34)
[Clang 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
➜  cpython git:(master) ./python.exe ../backups/bpo35530_1.py
XXX
ERROR:root:ZZZ
ERROR:main:XXX


root is parent for all logger objects created down the inheritance chain. When there is no root handler for logger then it resorts to lastResort handler (As per name called on last resort when there is no handler even for root) whose format is "%(message)s". Calling logging.error sets the root's handler (like doing logging.basicConfig). When there is a root with handler then subsequent logger calls the root's handler but lastResort is not called since it has found the root handler. I agree with Mark that this could affect downstream and is very hard to debug when libraries have wrong configuration.

import logging
logger = logging.getLogger(name='main')
logger.setLevel(logging.INFO)
logger.error('XXX')
print("logger parent ", logger.parent) # Root is always the parent by default
print("logger parent handlers ", logger.parent.handlers) # No root handler since root is not configured which logging error does below
print("logger handler ", logger.handlers) # Empty and no parent (root) handler so calls lastResort
logging.error('ZZZ') # Sets the root handler
print("logger parent after logging ", logger.parent) # Root is parent
print("logger parent handlers after logging ", logger.parent.handlers) # Root handler is set
print("logger handler after logging ", logger.handlers) # Empty but has parent (root) handler so lastResort is not called
logger.error('XXX')

Output : 

XXX
logger parent  <RootLogger root (WARNING)>
logger parent handlers  []
logger handler  []
ERROR:root:ZZZ
logger parent after logging  <RootLogger root (WARNING)>
logger parent handlers after logging  [<StreamHandler <stderr> (NOTSET)>]
logger handler after logging  []
ERROR:main:XXX

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue35530>
_______________________________________


More information about the Python-bugs-list mailing list