Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: matplotlib.set_loglevel() adds a console handler #23646

Closed
l-johnston opened this issue Aug 17, 2022 · 5 comments · Fixed by #24925
Closed

[Bug]: matplotlib.set_loglevel() adds a console handler #23646

l-johnston opened this issue Aug 17, 2022 · 5 comments · Fixed by #24925
Milestone

Comments

@l-johnston
Copy link
Contributor

Bug summary

matplotlib.set_loglevel() adds a logging console handler which then leads to duplicate messages in application code. The best practice is to allow the application code to add the handlers to its logger along with formatting, filtering, etc. The existing #13264 attempted to address this.

Code for reproduction

import logging
import matplotlib as mpl
mpl_logger = logging.getLogger("matplotlib")
mpl.set_loglevel("debug")
mpl_logger.hasHandlers()
logger = logging.getLogger()
ch = logging.StreamHandler()
logger.addHandler(ch)
logger.setLevel(logging.DEBUG)
import matplotlib.pyplot as plt

Actual outcome

True
DEBUG:matplotlib:CACHEDIR=C:\Users\ljohnsto.matplotlib
CACHEDIR=C:\Users\ljohnsto.matplotlib
DEBUG:matplotlib.font_manager:Using fontManager instance from C:\Users\ljohnsto.matplotlib\fontlist-v330.json
Using fontManager instance from C:\Users\ljohnsto.matplotlib\fontlist-v330.json

Expected outcome

False
CACHEDIR=C:\Users\ljohnsto.matplotlib
Using fontManager instance from C:\Users\ljohnsto.matplotlib\fontlist-v330.json

Additional information

The workaround is:

In [1]: import logging
In [2]: import matplotlib as mpl
In [3]: mpl_logger = logging.getLogger("matplotlib")
In [4]: mpl.set_loglevel("debug")
In [5]: mpl_logger_handlers = mpl_logger.handlers.copy()
In [6]: for h in mpl_logger_handlers:
   ...:     mpl_logger.removeHandler(h)
   ...:
In [7]: logger = logging.getLogger()
In [8]: ch = logging.StreamHandler()
In [9]: logger.addHandler(ch)
In [10]: logger.setLevel(logging.DEBUG)
In [11]: import matplotlib.pyplot as plt
CACHEDIR=C:\Users\ljohnsto\.matplotlib
Using fontManager instance from C:\Users\ljohnsto\.matplotlib\fontlist-v330.json
'''

### Operating system

Windows

### Matplotlib Version

3.5.2

### Matplotlib Backend

TkAgg

### Python version

3.9.13

### Jupyter version

_No response_

### Installation

pip
@jklymak
Copy link
Member

jklymak commented Aug 17, 2022

Yes agreed. But set_loglevel is meant to be a helper for endusers (eg our application) versus for downstream applications. Set matplotlibs log levels using the logging library if you have a downstream application.

@jklymak jklymak added the status: needs clarification Issues that need more information to resolve. label Aug 17, 2022
@l-johnston
Copy link
Contributor Author

@jklymak

  • The documentation for matplotlib.set_loglevel() doesn't indicate that Matplotlib is using the standard library logging. So, I thought I had to opt-in to get logging information through this function call.
  • It appears to me that the top level module matplotlib represents the library and matplotlib.pyplot represents the application - is this correct?
  • If so, perhaps move set_loglevel() to pyplot and provide a documentation section for logging generally.

@jklymak
Copy link
Member

jklymak commented Aug 19, 2022

A link to the standard logging library would make sense. I don't really see the point of a deprecation cycle for the top-level set_loglevel - it is already also exposed as pyplot.set_loglevel.

@jklymak jklymak added Documentation and removed status: needs clarification Issues that need more information to resolve. labels Aug 19, 2022
@tacaswell
Copy link
Member

The documentation for matplotlib.set_loglevel() doesn't indicate that Matplotlib is using the standard library logging. So, I thought I had to opt-in to get logging information through this function call.

fair, will open a PR to fix that. I'm also thinking about adding a keyword arguement to opt-opt of us trying to install a handler.

It appears to me that the top level module matplotlib represents the library and matplotlib.pyplot represents the application - is this correct?

We have not articulated in so many words, but this seems right. Historically the distinction has been a bit fuzzy, but we are slowly pushing things towards this state.

@tacaswell
Copy link
Member

xref #23681 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants