From 6f2840784bb3b74b2610edbc84cb85df28578a3c Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 19 Aug 2022 14:48:24 -0400 Subject: [PATCH 1/2] DOC: clarify that Matplotlib uses standard library logging module and that set_loglevel tries to be helpful and installs a stream handler. --- lib/matplotlib/__init__.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 50033b212a93..0de3e49e795e 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -232,12 +232,22 @@ def _ensure_handler(): def set_loglevel(level): """ - Set Matplotlib's root logger and root logger handler level, creating - the handler if it does not exist yet. + Configure Matplotlib's logging levels. + + Matplotlib uses the standard library `logging` framework under the root + logger 'matplotlib'. This is a helper function to: + + - set Matplotlib's root logger level + - set the root logger handler's level, creating the handler + if it does not exist yet Typically, one should call ``set_loglevel("info")`` or ``set_loglevel("debug")`` to get additional debugging information. + Users or applications that are installing their own logging handlers + may want to directly manipulate ``logging.getLogger('matplotlib')`` rather + than use this function. + Parameters ---------- level : {"notset", "debug", "info", "warning", "error", "critical"} @@ -248,6 +258,7 @@ def set_loglevel(level): The first time this function is called, an additional handler is attached to Matplotlib's root handler; this handler is reused every time and this function simply manipulates the logger and handler's level. + """ _log.setLevel(level.upper()) _ensure_handler().setLevel(level.upper()) From 1b1502d2f7047f267faf9f23ef5ee3f76fde96ab Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 19 Aug 2022 14:59:05 -0400 Subject: [PATCH 2/2] ENH: add ability for set_loglevel to not add a handler --- doc/users/next_whats_new/loggers.rst | 10 ++++++++++ lib/matplotlib/__init__.py | 11 ++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 doc/users/next_whats_new/loggers.rst diff --git a/doc/users/next_whats_new/loggers.rst b/doc/users/next_whats_new/loggers.rst new file mode 100644 index 000000000000..0c64998c6e3d --- /dev/null +++ b/doc/users/next_whats_new/loggers.rst @@ -0,0 +1,10 @@ +``set_loglevel`` can opt-out of manipulating logging handlers +------------------------------------------------------------- + +It is now possible to configure the logging level of the Matplotilb standard +library logger without also implicitly installing a handler via both +`matplotlib.set_loglevel` and `matplotlib.pyplot.set_loglevel` :: + + mpl.set_loglevel('debug', ensure_handler=False) + # or + plt.set_loglevel('debug', ensure_handler=False) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 0de3e49e795e..3b4f9aa76876 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -230,7 +230,7 @@ def _ensure_handler(): return handler -def set_loglevel(level): +def set_loglevel(level, *, ensure_handler=True): """ Configure Matplotlib's logging levels. @@ -238,7 +238,7 @@ def set_loglevel(level): logger 'matplotlib'. This is a helper function to: - set Matplotlib's root logger level - - set the root logger handler's level, creating the handler + - optionally set the root logger handler's level, creating the handler if it does not exist yet Typically, one should call ``set_loglevel("info")`` or @@ -253,6 +253,10 @@ def set_loglevel(level): level : {"notset", "debug", "info", "warning", "error", "critical"} The log level of the handler. + ensure_handler : bool + If True will ensure that there is a `logging.StreamHandler` added to + the matplotlib root logger and that its level matches the logger level. + Notes ----- The first time this function is called, an additional handler is attached @@ -261,7 +265,8 @@ def set_loglevel(level): """ _log.setLevel(level.upper()) - _ensure_handler().setLevel(level.upper()) + if ensure_handler: + _ensure_handler().setLevel(level.upper()) def _logged_cached(fmt, func=None):