Repository navigation
Logging cache not cleared properly when setting level #81439
Description
Activity
If you call setLevel() on a subclass of logging.Logger, it does not reset the cache for that logger. This mean that if you make some logging calls, then call setLevel(), the logger still acts like it still has its old level. See the attached python file for a reference.
Currently, the user has to call logger._cache.clear() to manually clear the cache after calling setLevel(). To fix this in Python, we would have to change Logger.setLevel() in /logging/init.py to have the following code
self.level = _checkLevel(level) self.manager._clear_cache() self._cache.clear()Note the following:
- I made sure the subclass has a handler attached so setLevel() should work
- This bug does not occur if you use logging.getLogger(). This is because logging.getLogger() returns the root logger, and the cache clear specifically targets the root logger's cache to be cleared. It occurs when the logger is specifically subclassed from logging.getLoggerClass()
- The cache was added in Python 3.7, so this bug is specific to this version of python.
- added3.7 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Jun 12, 2019 A unittest patch for this issue. This occurs in master and 3.8 too.
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 50148dc2f2..30fd9ee37a 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -4172,6 +4172,27 @@ class ModuleLevelMiscTest(BaseTest):
logging.setLoggerClass(logging.Logger)
self.assertEqual(logging.getLoggerClass(), logging.Logger)+ def test_subclass_logger_cache(self):
+
+ class MyLogger(logging.getLoggerClass()):
+ pass
+
+ logger = MyLogger('test')
+ stream = io.StringIO()
+ h = logging.StreamHandler(stream)
+ logger.addHandler(h)
+
+ logger.setLevel(logging.DEBUG)
+ logger.debug("hello")
+ self.assertEqual(stream.getvalue().strip(), "hello")
+
+ stream.truncate(0)
+ stream.seek(0)
+
+ logger.setLevel(logging.INFO)
+ logger.debug("hello")
+ self.assertEqual(stream.getvalue(), "")
+
@support.requires_type_collecting
def test_logging_at_shutdown(self):
# Issue bpo-20037This is not actually a bug, but happens because the logger is instantiated directly, rather than through logging.getLogger(...). Because of the direct instantiation, the logger cache isn't tracked via setLevel() - because the logger doesn't end up in logging.manager.loggerDict.
However, I will incorporate Karthikeyan's test (modified to avoid direct instantiation), and update the documentation to strengthen the information to avoid direct instantiation of loggers.
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: