Simple logging interface. · matplotlib/matplotlib@a5f43ac · GitHub
Skip to content

Commit a5f43ac

Browse files
committed
Simple logging interface.
1 parent 2660901 commit a5f43ac

5 files changed

Lines changed: 64 additions & 69 deletions

File tree

doc/devel/contributing.rst

Lines changed: 10 additions & 6 deletions

doc/faq/troubleshooting_faq.rst

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -114,35 +114,18 @@ provide the following information in your e-mail to the `mailing list
114114
the error will help you find a bug in *your* code that is causing the
115115
problem.
116116

117-
* You can get helpful debugging output from Matlotlib by using the `logging`
118-
library in your code and posting the verbose output to the lists. For a
119-
command-line version of this, try::
117+
* Matplotlib provides debugging information through the `logging` library, and
118+
a helper function to set the logging level: one can call ::
120119

121-
python -c "from logging import *; basicConfig(level=DEBUG); from pylab import *; plot(); show()"
120+
import matplotlib
121+
matplotlib.set_loglevel("info") # or "debug" for more info
122122

123+
to obtain this debugging information.
123124

124-
If you want to put the debugging hooks in your own code, then the
125-
most simple way to do so is to insert the following *before* any calls
126-
to ``import matplotlib``::
127-
128-
import logging
129-
logging.basicConfig(level=logging.DEBUG)
130-
131-
import matplotlib.pyplot as plt
132-
133-
Note that if you want to use `logging` in your own code, but do not
134-
want verbose Matplotlib output, you can set the logging level
135-
for Matplotlib independently::
136-
137-
import logging
138-
# set DEBUG for everything
139-
logging.basicConfig(level=logging.DEBUG)
140-
logger = logging.getLogger('matplotlib')
141-
# set WARNING for Matplotlib
142-
logger.setLevel(logging.WARNING)
143-
144-
The `logging` module is very flexible, and can be a valuable tool in chasing
145-
down errors.
125+
(Standard functions from the `logging` module are also applicable; e.g. one
126+
could call ``logging.basicConfig(level="DEBUG")`` even before importing
127+
Matplotlib, or attach a custom handler to the "matplotlib" logger. This may
128+
be useful if you use a custom logging configuration.)
146129

147130
If you compiled Matplotlib yourself, please also provide:
148131

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
:orphan:
2+
3+
New logging API
4+
```````````````
5+
6+
`matplotlib.set_loglevel`/`.pyplot.set_loglevel` can be called to display more
7+
(or less) detailed logging output.

lib/matplotlib/__init__.py

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -207,48 +207,43 @@ def _check_versions():
207207
sys.argv = ['modpython']
208208

209209

210-
_verbose_msg = """\
211-
matplotlib.verbose is deprecated;
212-
Command line argument --verbose-LEVEL is deprecated.
213-
This functionality is now provided by the standard
214-
python logging library. To get more (or less) logging output:
215-
import logging
216-
logger = logging.getLogger('matplotlib')
217-
logger.set_level(logging.INFO)"""
210+
# The decorator ensures this always returns the same handler (and it is only
211+
# attached once).
212+
@functools.lru_cache()
213+
def _ensure_handler():
214+
"""
215+
The first time this function is called, attach a `StreamHandler` using the
216+
same format as `logging.basicConfig` to the Matplotlib root logger.
217+
218+
Return this handler every time this function is called.
219+
"""
220+
handler = logging.StreamHandler()
221+
handler.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
222+
_log.addHandler(handler)
223+
return handler
218224

219225

220-
def _set_logger_verbose_level(level_str='silent', file_str='sys.stdout'):
226+
def set_loglevel(level):
221227
"""
222-
Use a --verbose-LEVEL level to set the logging level:
228+
Sets the Matplotlib's root logger and root logger handler level, creating
229+
the handler if it does not exist yet.
223230
231+
Typically, one should call ``set_loglevel("info")`` or
232+
``set_loglevel("debug")`` to get additional debugging information.
233+
234+
Parameters
235+
----------
236+
level : {"notset", "debug", "info", "warning", "error", "critical"}
237+
The log level of the handler.
238+
239+
Notes
240+
-----
241+
The first time this function is called, an additional handler is attached
242+
to Matplotlib's root handler; this handler is reused every time and this
243+
function simply manipulates the logger and handler's level.
224244
"""
225-
levelmap = {'silent': logging.WARNING, 'helpful': logging.INFO,
226-
'debug': logging.DEBUG, 'debug-annoying': logging.DEBUG,
227-
'info': logging.INFO, 'warning': logging.WARNING}
228-
# Check that current state of logger isn't already more verbose
229-
# than the requested level. If it is more verbose, then leave more
230-
# verbose.
231-
newlev = levelmap[level_str]
232-
oldlev = _log.getEffectiveLevel()
233-
if newlev < oldlev:
234-
_log.setLevel(newlev)
235-
std = {
236-
'sys.stdout': sys.stdout,
237-
'sys.stderr': sys.stderr,
238-
}
239-
if file_str in std:
240-
fileo = std[file_str]
241-
else:
242-
fileo = sys.stdout
243-
try:
244-
fileo = open(file_str, 'w')
245-
# if this fails, we will just write to stdout
246-
except IOError:
247-
_log.warning('could not open log file "{0}" for writing. '
248-
'Check your matplotlibrc'.format(file_str))
249-
console = logging.StreamHandler(fileo)
250-
console.setLevel(newlev)
251-
_log.addHandler(console)
245+
_log.setLevel(level.upper())
246+
_ensure_handler().setLevel(level.upper())
252247

253248

254249
def _logged_cached(fmt, func=None):

lib/matplotlib/pyplot.py

Lines changed: 6 additions & 0 deletions

0 commit comments

Comments
 (0)