10000 ENH: add a user-friendly verbose interface by jklymak · Pull Request #13129 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

ENH: add a user-friendly verbose interface #13129

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

Closed
wants to merge 1 commit into from

Conversation

jklymak
Copy link
Member
@jklymak jklymak commented Jan 7, 2019

EDIT: updated to change default ot INFO

PR Summary

A simple verbose interface that turns on the logging module for matplotlib:

import matplotlib.pyplot as plt
plt.verbose()  # or plt.verbose('info') or plt.verbose(True)

Now all _log.info() and more urgent messages will be printed.

import matplotlib.pyplot as plt
plt.debug()  # or plt.verbose('debug') 

for more info.

and

import matplotlib.pyplot as plt
plt.verbose('warning')  # or plt.verbose(False)

to get back to standard logging level.

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@jklymak jklymak changed the title ENH: add a user-freindly verbose interface ENH: add a user-friendly verbose interface Jan 7, 2019
If True set logging level to "DEBUG" for matplotlib module.
If FALSE set logging level to "WARNING" for matplotlib module (this
is the default level if ``verbose`` is not called). If a string, must
be one of ['warning', 'info', 'debug'], in order of increasing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But standard Python logging has more levels than this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah there is critical and something else I can’t remember. Did we want to support quieting the more critical levels? To my knowledge we never use those levels anyhow.

@WeatherGod
Copy link
Member
WeatherGod commented Jan 8, 2019 via email

@tacaswell tacaswell added this to the v3.1 milestone Jan 8, 2019
@tacaswell
Copy link
Member

I thought we agreed to make the default behavior to 'info'?

@jklymak
Copy link
Member Author
jklymak commented Jan 8, 2019

I think if we tell the naive user to do plt.verbose() and send us the output, it should spit out as much as possible. But don't feel strongly about it either way.

@jklymak
Copy link
Member Author
jklymak commented Jan 8, 2019

BTW can we remove the class Verbose. All its methods were deprecated in 2.2. Removing it would allow matplotlib.verbose method instead of matplotlib.set_verbose.

Ooops, never mind. #12245 removed Verbose. It also removed matplotlib --verbose-debug. While I agree that was deprecated, not 100% sure it should go away.

Note now that matplotlib.verbose() still exists, but has changed meaning from the deprecated meaning in 3.0.2. Not sure if that is acceptable. I really doubt it'd catch too many people, but...

@jklymak jklymak force-pushed the enh-add-verbose-interface branch 2 times, most recently from 6dc8ed9 to 1bcf4f4 Compare January 8, 2019 17:10
import logging
logger = logging.getLogger('matplotlib')
logger.set_level(logging.INFO)"""
def verbose(level='debug'):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems largely redundant with _set_logger_verbose_level. Wouldn't it be sufficient to have one public function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe - I wasnt' aware that the command line handling was gone in master when I did this. If we really think the commad line handling can go away, then I agree. But I'm not sure we should fully drop the commandline option.

If we merge, do we want to keep the filestr argument to allow re-direct of the log?

The point here was to give naive users an easy way to spit out verbose info so I'm not convnced a file redirect is a good idea.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn’t erase the function, but don’t use it anymore... I didn’t erase just because I’m not sure I could recreate the code from scratch...

@WeatherGod
Copy link
Member
WeatherGod commented Jan 8, 2019 via email

@tacaswell
Copy link
Member

I think if we tell the naive user to do plt.verbose() and send us the output, it should spit out as much as possible. But don't feel strongly about it either way.

I thought part of this was to allow there to be a "helpful but not painfully verbose" level that many users could just have on day-to-day.

@jklymak
Copy link
Member Author
jklymak commented Jan 8, 2019

I'm flexible on either use

Poll: plt.verbose() yields less verbose INFO level log output. Thumbs up. Thumbs down if it should default to more spammy DEBUG.

@jklymak
Copy link
Member Author
jklymak commented Jan 8, 2019

... we could also have a plt.debug I guess

EDIT: done....

Copy link
Member
@NelleV NelleV left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new function should be documented in our "what's new", and the following documentation files probably need to be updated (just did a git grep logging):

  • devel/contributing.rst
  • faq/troubleshooting_faq.rst

Thanks!

matplotlib.verbose(level=level)


def debug():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I don't have a strong opinion about my comment)

Do we really need this shortcut? It seems very redundant with verbose()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea here is to tell the user to do one thing and plt.debug() is (a bit) easier than plt.verbose('debgug'). Originally I wanted plt.verbose to go to debug, but @tacaswell thought it should just be info.

Copy link
Member
@timhoffm timhoffm Jan 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplifying plt.verbose('debug') to plt.debug() is unnecessary. Our users know how to pass a parameter. And it's not even that they have to call this function often. I'm afraid it would even be more confusing. As a user, I would ask myself: Is there a difference between those two? There should be only one function for setting the log level.

I also recommend naming the function plt.set_loglevel(), which is more in line with the terminology of the logging module. "verbose" was coming from the command line interface. In this world it as a well-known meaning. Not so in Python code. Here, the well-known entity for controlling output is the log level. Since Matplotlib is a library we should stick to that terminology.

logger.set_level(logging.INFO)"""
def verbose(level='debug'):
"""
Shortcut to set the debugging level of the logging module.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking about the wording here. This function doesn't really set a debugging level of the logging module, but a logging level to "debug" (or warning).

@@ -1997,6 +1997,49 @@ def colormaps():
return sorted(cm.cmap_d)


def verbose(level='info'):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't have the same default as matplotlib.verbose...
FWIW I would just do from matplotlib import verbose and be done with it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will that show up in the pyplot docs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the defaults.

@jklymak
Copy link
Member Author
jklymak commented Jan 19, 2019

Updated documentation. Thanks!

@jklymak
Copy link
Member Author
jklymak commented Jan 20, 2019

Opinions on plt.set_loglevel() instead of plt.verbose. I don't mind either way, but don't want to go in circles with different names. Thumbs up for set_loglevel, down for verbose.

@jklymak jklymak force-pushed the enh-add-verbose-interface branch from a3b9635 to b598ea9 Compare January 21, 2019 21:25
More straight forward helper methods are available to end-users as well::

import matplotlib.pyplot as plt
plt.set_loglevel(level='info') # or plt.set_loglevel(level='debug')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
plt.set_loglevel(level='info') # or plt.set_loglevel(level='debug')
plt.set_loglevel('info') # or plt.set_loglevel('debug')

Since there is only one parameter and the function name already tells it, I propose the canonical way of using this is with a positional parameter.

most simple way to do so is to insert the following *before* any calls
to ``import matplotlib``::
import matplotlib.pyplot as plt
plt.set_loglevel(level='info') # or plt.set_loglevel(level='debug')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
plt.set_loglevel(level='info') # or plt.set_loglevel(level='debug')
plt.set_loglevel('info') # or plt.set_loglevel('debug')

See above.


Parameters
----------
level : str or bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO there is no natural mapping from bool to log levels. I would discard the bool option.
set_loglevel(True) is less clear and only slightly less to type compared to set_loglevel('info').

import logging
logger = logging.getLogger('matplotlib')
logger.set_level(logging.INFO)"""
def set_loglevel(level='info'):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a default? Just from set_loglevel() I couldn't guess what level is now in use. Having to pass the level makes it explicit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree with this. The only reason it is ambiguous is you suggested we change the name from verbose 😉 The naive user posting on stack overflow is not going to know the names of the logging levels so having an interface where they don’t have to pass an argument is desirable.

@danielballan
Copy link
Contributor

Have you considered adding a special logging handler and having plt.set_loglevel adjust the level on the handler instead of the level on the 'matplotlib' logger? The user experience would be the same, but adjusting the handler level instead of the logger level would allow externally-managed handlers to work with their own set of level settings without mutual interference.

As a concrete example, I work at a facility that configures INFO-level loggers on several libraries and ships the output to a centralized system in order to support visiting users. I would like my users to have the freedom to, separately, add loggers at any level -- such as via plt.set_loglevel(...). If the level-setting is performed on the handlers and never on the loggers, these two systems can operate harmoniously.

@jklymak
Copy link
Member Author
jklymak commented Jan 22, 2019

@danielballan I suppose something like that can work, but I'd need more details and an argument why the extra complexity is worth it. No one has to call these methods, so I'm not sure why a specialized system would need to use this rather than configure logging on their own. But I really don't know the logging system very well, so if there is a good argument to be made for the extra layer...

@danielballan
Copy link
Contributor

Now that I read more deeply, the complexity that I am asking for is already implemented in matplotlib's _set_logger_verbose_level, which your new function calls. It configures a StreamHandler, set the desired level there, and ensures the current level of the matplotlib logger is at least as verbose as the level of the handler. Both steps are necessary for log messages to propagate and be emitted.

As a separate concern, I was surprised that matplotlib.set_loglevel("DEBUG") raised a KeyError. That is Python's canonical way to spell it -- as in logging.getLogger('matplotlib').setLevel('DEBUG'). Adding a call to .upper() or .lower() somewhere might be nice.

ENH: set level to INFO and add pyplot.debug()
DOC: add whats new and update FAQs
DOC: fix wording
ENH: change name to set_loglevel
FIX: lower case
@jklymak jklymak force-pushed the enh-add-verbose-interface branch from b598ea9 to e575fc7 Compare January 22, 2019 15:57
@jklymak
Copy link
Member Author
jklymak commented Jan 22, 2019

Adding a call to .upper() or .lower() somewhere might be nice.

Done!

Copy link
Member
@timhoffm timhoffm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're using logging the wrong way and this PR is just a symptom of that.

See #13264 for a discussion on the topic.

Until that's discussed, I would like to hold this PR back.

@anntzer anntzer mentioned this pull request Jan 24, 2019
6 tasks
@jklymak
Copy link
Member Author
jklymak commented Jan 25, 2019

I'll close in lieu of #13275

@jklymak jklymak closed this Jan 25, 2019
@jklymak jklymak deleted the enh-add-verbose-interface branch January 25, 2019 03:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants
0