diff --git a/doc/devel/contributing.rst b/doc/devel/contributing.rst index 5140260b3f63..a90dc1694d6a 100644 --- a/doc/devel/contributing.rst +++ b/doc/devel/contributing.rst @@ -435,18 +435,22 @@ To include `logging` in your module, at the top of the module, you need to will log to a logger named ``matplotlib.yourmodulename``. If an end-user of Matplotlib sets up `logging` to display at levels -more verbose than `logger.WARNING` in their code as follows:: +more verbose than `logger.WARNING` in their code with the Matplotlib-provided +helper:: + + plt.set_loglevel("debug") + +or manually with :: import logging - fmt = '%(name)s:%(lineno)5d - %(levelname)s - %(message)s' - logging.basicConfig(level=logging.DEBUG, format=fmt) + logging.basicConfig(level=logging.DEBUG) import matplotlib.pyplot as plt Then they will receive messages like:: - matplotlib.backends: 89 - INFO - backend MacOSX version unknown - matplotlib.yourmodulename: 347 - INFO - Here is some information - matplotlib.yourmodulename: 348 - DEBUG - Here is some more detailed information + DEBUG:matplotlib.backends:backend MacOSX version unknown + DEBUG:matplotlib.yourmodulename:Here is some information + DEBUG:matplotlib.yourmodulename:Here is some more detailed information Which logging level to use? ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/faq/troubleshooting_faq.rst b/doc/faq/troubleshooting_faq.rst index 7002156948e2..3511a2141271 100644 --- a/doc/faq/troubleshooting_faq.rst +++ b/doc/faq/troubleshooting_faq.rst @@ -114,35 +114,18 @@ provide the following information in your e-mail to the `mailing list the error will help you find a bug in *your* code that is causing the problem. -* You can get helpful debugging output from Matlotlib by using the `logging` - library in your code and posting the verbose output to the lists. For a - command-line version of this, try:: +* Matplotlib provides debugging information through the `logging` library, and + a helper function to set the logging level: one can call :: - python -c "from logging import *; basicConfig(level=DEBUG); from pylab import *; plot(); show()" + plt.set_loglevel("info") # or "debug" for more info + to obtain this debugging information. - If you want to put the debugging hooks in your own code, then the - most simple way to do so is to insert the following *before* any calls - to ``import matplotlib``:: - - import logging - logging.basicConfig(level=logging.DEBUG) - - import matplotlib.pyplot as plt - - Note that if you want to use `logging` in your own code, but do not - want verbose Matplotlib output, you can set the logging level - for Matplotlib independently:: - - import logging - # set DEBUG for everything - logging.basicConfig(level=logging.DEBUG) - logger = logging.getLogger('matplotlib') - # set WARNING for Matplotlib - logger.setLevel(logging.WARNING) - - The `logging` module is very flexible, and can be a valuable tool in chasing - down errors. + Standard functions from the `logging` module are also applicable; e.g. one + could call ``logging.basicConfig(level="DEBUG")`` even before importing + Matplotlib (this is in particular necessary to get the logging info emitted + during Matplotlib's import), or attach a custom handler to the "matplotlib" + logger. This may be useful if you use a custom logging configuration. If you compiled Matplotlib yourself, please also provide: diff --git a/doc/users/next_whats_new/2019-01-24-AL-set_loglevel.rst b/doc/users/next_whats_new/2019-01-24-AL-set_loglevel.rst new file mode 100644 index 000000000000..9649ed80f481 --- /dev/null +++ b/doc/users/next_whats_new/2019-01-24-AL-set_loglevel.rst @@ -0,0 +1,7 @@ +:orphan: + +New logging API +``````````````` + +`matplotlib.set_loglevel`/`.pyplot.set_loglevel` can be called to display more +(or less) detailed logging output. diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 97c7fd5f05be..566cc14832aa 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -206,48 +206,43 @@ def _check_versions(): sys.argv = ['modpython'] -_verbose_msg = """\ -matplotlib.verbose is deprecated; -Command line argument --verbose-LEVEL is deprecated. -This functionality is now provided by the standard -python logging library. To get more (or less) logging output: - import logging - logger = logging.getLogger('matplotlib') - logger.set_level(logging.INFO)""" +# The decorator ensures this always returns the same handler (and it is only +# attached once). +@functools.lru_cache() +def _ensure_handler(): + """ + The first time this function is called, attach a `StreamHandler` using the + same format as `logging.basicConfig` to the Matplotlib root logger. + + Return this handler every time this function is called. + """ + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter(logging.BASIC_FORMAT)) + _log.addHandler(handler) + return handler -def _set_logger_verbose_level(level_str='silent', file_str='sys.stdout'): +def set_loglevel(level): """ - Use a --verbose-LEVEL level to set the logging level: + Sets the Matplotlib's root logger and root logger handler 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. + + Parameters + ---------- + level : {"notset", "debug", "info", "warning", "error", "critical"} + The log level of the handler. + + Notes + ----- + 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. """ - levelmap = {'silent': logging.WARNING, 'helpful': logging.INFO, - 'debug': logging.DEBUG, 'debug-annoying': logging.DEBUG, - 'info': logging.INFO, 'warning': logging.WARNING} - # Check that current state of logger isn't already more verbose - # than the requested level. If it is more verbose, then leave more - # verbose. - newlev = levelmap[level_str] - oldlev = _log.getEffectiveLevel() - if newlev < oldlev: - _log.setLevel(newlev) - std = { - 'sys.stdout': sys.stdout, - 'sys.stderr': sys.stderr, - } - if file_str in std: - fileo = std[file_str] - else: - fileo = sys.stdout - try: - fileo = open(file_str, 'w') - # if this fails, we will just write to stdout - except IOError: - _log.warning('could not open log file "{0}" for writing. ' - 'Check your matplotlibrc'.format(file_str)) - console = logging.StreamHandler(fileo) - console.setLevel(newlev) - _log.addHandler(console) + _log.setLevel(level.upper()) + _ensure_handler().setLevel(level.upper()) def _logged_cached(fmt, func=None): diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 140aa451e0a2..52a2e1322d65 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -18,6 +18,7 @@ The object-oriented API is recommended for more complex plots. """ +import functools import importlib import inspect import logging @@ -166,6 +167,11 @@ def uninstall_repl_displayhook(): draw_all = _pylab_helpers.Gcf.draw_all +@functools.wraps(matplotlib.set_loglevel) +def set_loglevel(*args, **kwargs): # Ensure this appears in the pyplot docs. + return matplotlib.set_loglevel(*args, **kwargs) + + @docstring.copy(Artist.findobj) def findobj(o=None, match=None, include_self=True): if o is None:
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: