Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit477c1dc

Browse files
authored
Merge pull request#9313 from jklymak/logging
Replace verbose class with standard logging library
2 parents7252158 +844877c commit477c1dc

24 files changed

+436
-250
lines changed

‎doc/devel/contributing.rst

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ repository <https://github.com/matplotlib/matplotlib/>`__ on GitHub,
171171
then submit a "pull request" (PR).
172172

173173
The best practices for using GitHub to make PRs to Matplotlib are
174-
documented in the:ref:`development-workflow` section.
174+
documented in the:ref:`development-workflow` section.
175175

176176
A brief overview is:
177177

@@ -437,6 +437,70 @@ forced to use ``**kwargs``. An example is
437437
elif len(args) == 1:
438438
...etc...
439439

440+
.. _using_logging:
441+
442+
Using logging for debug messages
443+
--------------------------------
444+
445+
Matplotlib uses the standard python `logging` library to write verbose
446+
warnings, information, and
447+
debug messages. Please use it! In all those places you write:func:`print()`
448+
statements to do your debugging, try using:func:`log.debug()` instead!
449+
450+
451+
To include `logging` in your module, at the top of the module, you need to
452+
``import logging``. Then calls in your code like::
453+
454+
_log = logging.getLogger(__name__) # right after the imports
455+
456+
# code
457+
# more code
458+
_log.info('Here is some information')
459+
_log.debug('Here is some more detailed information')
460+
461+
will log to a logger named ``matplotlib.yourmodulename``.
462+
463+
If an end-user of Matplotlib sets up `logging` to display at levels
464+
more verbose than `logger.WARNING` in their code as follows::
465+
466+
import logging
467+
fmt = '%(name)s:%(lineno)5d - %(levelname)s - %(message)s'
468+
logging.basicConfig(level=logging.DEBUG, format=fmt)
469+
import matplotlib.pyplot as plt
470+
471+
Then they will receive messages like::
472+
473+
matplotlib.backends: 89 - INFO - backend MacOSX version unknown
474+
matplotlib.yourmodulename: 347 - INFO - Here is some information
475+
matplotlib.yourmodulename: 348 - DEBUG - Here is some more detailed information
476+
477+
Which logging level to use?
478+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
479+
480+
There are five levels at which you can emit messages.
481+
`logging.critical` and `logging.error`
482+
are really only there for errors that will end the use of the library but
483+
not kill the interpreter. `logging.warning` overlaps with the
484+
``warnings`` library. The
485+
`logging tutorial<https://docs.python.org/3/howto/logging.html#logging-basic-tutorial>`_
486+
suggests that the difference
487+
between `logging.warning` and `warnings.warn` is that
488+
`warnings.warn` be used for things the user must change to stop
489+
the warning, whereas `logging.warning` can be more persistent.
490+
491+
By default, `logging` displays all log messages at levels higher than
492+
`logging.WARNING` to `sys.stderr`.
493+
494+
Calls to `logging.info` are not displayed by default. They are for
495+
information that the user may want to know if the program behaves oddly.
496+
For instance, if an object isn't drawn because its position is ``NaN``,
497+
that can usually be ignored, but a mystified user could set
498+
``logging.basicConfig(level=logging.INFO)`` and get an error message that
499+
says why.
500+
501+
`logging.debug` is the least likely to be displayed, and hence can
502+
be the most verbose.
503+
440504
.. _custom_backend:
441505

442506
Developing a new backend

‎doc/faq/troubleshooting_faq.rst

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ Troubleshooting
99

1010
.. _matplotlib-version:
1111

12-
Obtainingmatplotlib version
12+
ObtainingMatplotlib version
1313
============================
1414

15-
To find out yourmatplotlib version number, import it and print the
15+
To find out yourMatplotlib version number, import it and print the
1616
``__version__`` attribute::
1717

1818
>>> import matplotlib
@@ -25,7 +25,7 @@ To find out your matplotlib version number, import it and print the
2525
:file:`matplotlib` install location
2626
===================================
2727

28-
You can find what directorymatplotlib is installed in by importing it
28+
You can find what directoryMatplotlib is installed in by importing it
2929
and printing the ``__file__`` attribute::
3030

3131
>>> import matplotlib
@@ -37,7 +37,7 @@ and printing the ``__file__`` attribute::
3737
:file:`matplotlib` configuration and cache directory locations
3838
==============================================================
3939

40-
Each user has amatplotlib configuration directory which may contain a
40+
Each user has aMatplotlib configuration directory which may contain a
4141
:ref:`matplotlibrc<customizing-with-matplotlibrc-files>` file. To
4242
locate your:file:`matplotlib/` configuration directory, use
4343
:func:`matplotlib.get_configdir`::
@@ -79,7 +79,7 @@ directory and the cache directory.
7979
Getting help
8080
============
8181

82-
There are a number of good resources for getting help withmatplotlib.
82+
There are a number of good resources for getting help withMatplotlib.
8383
There is a good chance your question has already been asked:
8484

8585
- The `mailing list archive<http://matplotlib.1069221.n5.nabble.com/>`_.
@@ -114,11 +114,35 @@ 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 getveryhelpful debugging output frommatlotlib byrunning your
118-
script with a ``verbose-helpful`` or ``--verbose-debug`` flags and posting
119-
the verbose output the lists::
117+
* You can get helpful debugging output fromMatlotlib byusing the `logging`
118+
library in your code and posting theverbose output to the lists. For a
119+
command-line version of this, try::
120120

121-
python simple_plot.py --verbose-helpful > output.txt
121+
python -c "from logging import *; basicConfig(level=DEBUG); from pylab import *; plot(); show()"
122+
123+
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.
122146

123147
If you compiled Matplotlib yourself, please also provide:
124148

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Logging for debug output
2+
------------------------
3+
4+
Matplotlib has in the past (sporadically) used an internal
5+
verbose-output reporter. This version converts those calls to using the
6+
standard python `logging` library.
7+
8+
Support for the old ``rcParams`` ``verbose.level`` and ``verbose.fileo`` is
9+
dropped.
10+
11+
The command-line options ``--verbose-helpful`` and ``--verbose-debug`` are
12+
still accepted, but deprecated. They are now equivalent to setting
13+
``logging.INFO`` and ``logging.DEBUG``.
14+
15+
The logger's root name is ``matplotlib`` and can be accessed from programs
16+
as::
17+
18+
import logging
19+
mlog = logging.getLogger('matplotlib')
20+
21+
Instructions for basic usage are in:ref:`troubleshooting-faq` and for
22+
developers in:ref:`contributing`.
23+
24+
.. _logging:https://docs.python.org/3/library/logging.html

‎lib/matplotlib/__init__.py

Lines changed: 109 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
importinspect
114114
importitertools
115115
importlocale
116+
importlogging
116117
importos
117118
importre
118119
importsys
@@ -137,6 +138,8 @@
137138
__version__=str(get_versions()['version'])
138139
delget_versions
139140

141+
_log=logging.getLogger(__name__)
142+
140143
__version__numpy__=str('1.7.1')# minimum required numpy version
141144

142145
__bibtex__=r"""@Article{Hunter:2007,
@@ -160,6 +163,9 @@
160163
ifnot (_python27or_python34):
161164
raiseImportError("Matplotlib requires Python 2.7 or 3.4 or later")
162165

166+
if_python27:
167+
_log.addHandler(logging.NullHandler())
168+
163169

164170
defcompare_versions(a,b):
165171
"return True if a is greater than or equal to b"
@@ -215,7 +221,75 @@ def _is_writable_dir(p):
215221
"""
216222
returnos.access(p,os.W_OK)andos.path.isdir(p)
217223

224+
_verbose_msg="""\
225+
Command line argument --verbose-LEVEL is deprecated.
226+
This functionality is now provided by the standard
227+
python logging library. To get more (or less) logging output:
228+
import logging
229+
logger = logging.getLogger('matplotlib')
230+
logger.set_level(logging.INFO)"""
231+
232+
233+
def_set_logger_verbose_level(level_str='silent',file_str='sys.stdout'):
234+
"""
235+
Use a --verbose-LEVEL level to set the logging level:
236+
237+
"""
238+
levelmap= {'silent':logging.WARNING,'helpful':logging.INFO,
239+
'debug':logging.DEBUG,'debug-annoying':logging.DEBUG,
240+
'info':logging.INFO,'warning':logging.WARNING}
241+
# Check that current state of logger isn't already more verbose
242+
# than the requested level. If it is more verbose, then leave more
243+
# verbose.
244+
newlev=levelmap[level_str]
245+
oldlev=_log.getEffectiveLevel()
246+
ifnewlev<oldlev:
247+
_log.setLevel(newlev)
248+
std= {
249+
'sys.stdout':sys.stdout,
250+
'sys.stderr':sys.stderr,
251+
}
252+
iffile_strinstd:
253+
fileo=std[file_str]
254+
else:
255+
fileo=sys.stdout
256+
try:
257+
fileo=open(file_str,'w')
258+
# if this fails, we will just write to stdout
259+
exceptIOError:
260+
warnings.warn('could not open log file "{0}"'
261+
'for writing. Check your '
262+
'matplotlibrc'.format(file_str))
263+
console=logging.StreamHandler(fileo)
264+
console.setLevel(newlev)
265+
_log.addHandler(console)
266+
267+
268+
def_parse_commandline():
269+
"""
270+
Check for --verbose-LEVEL type command line arguments and
271+
set logging level appropriately.
272+
"""
218273

274+
levels= ('silent','helpful','debug','debug-annoying',
275+
'info','warning')
276+
277+
forarginsys.argv[1:]:
278+
# cast to str because we are using unicode_literals,
279+
# and argv is always str
280+
281+
ifarg.startswith(str('--verbose-')):
282+
level_str=arg[10:]
283+
# If it doesn't match one of ours, then don't even
284+
# bother noting it, we are just a 3rd-party library
285+
# to somebody else's script.
286+
iflevel_strinlevels:
287+
_set_logger_verbose_level(level_str)
288+
289+
_parse_commandline()
290+
291+
292+
@cbook.deprecated("2.2",message=_verbose_msg)
219293
classVerbose(object):
220294
"""
221295
A class to handle reporting. Set the fileo attribute to any file
@@ -311,7 +385,29 @@ def ge(self, level):
311385
returnself.vald[self.level]>=self.vald[level]
312386

313387

314-
verbose=Verbose()
388+
def_wrap(fmt,func,level='INFO',always=True):
389+
"""
390+
return a callable function that wraps func and reports its
391+
output through logger
392+
393+
if always is True, the report will occur on every function
394+
call; otherwise only on the first time the function is called
395+
"""
396+
assertcallable(func)
397+
398+
defwrapper(*args,**kwargs):
399+
ret=func(*args,**kwargs)
400+
401+
if (alwaysornotwrapper._spoke):
402+
lvl=logging.getLevelName(level.upper())
403+
_log.log(lvl,fmt%ret)
404+
spoke=True
405+
ifnotwrapper._spoke:
406+
wrapper._spoke=spoke
407+
returnret
408+
wrapper._spoke=False
409+
wrapper.__doc__=func.__doc__
410+
returnwrapper
315411

316412

317413
defcheckdep_dvipng():
@@ -512,7 +608,7 @@ def _create_tmp_config_dir():
512608
returnconfigdir
513609

514610

515-
get_home=verbose.wrap('$HOME=%s',_get_home,always=False)
611+
get_home=_wrap('$HOME=%s',_get_home,always=False)
516612

517613

518614
def_get_xdg_config_dir():
@@ -601,7 +697,7 @@ def _get_configdir():
601697
"""
602698
return_get_config_or_cache_dir(_get_xdg_config_dir())
603699

604-
get_configdir=verbose.wrap('CONFIGDIR=%s',_get_configdir,always=False)
700+
get_configdir=_wrap('CONFIGDIR=%s',_get_configdir,always=False)
605701

606702

607703
def_get_cachedir():
@@ -613,7 +709,7 @@ def _get_cachedir():
613709
"""
614710
return_get_config_or_cache_dir(_get_xdg_cache_dir())
615711

616-
get_cachedir=verbose.wrap('CACHEDIR=%s',_get_cachedir,always=False)
712+
get_cachedir=_wrap('CACHEDIR=%s',_get_cachedir,always=False)
617713

618714

619715
def_decode_filesystem_path(path):
@@ -671,8 +767,8 @@ def _get_data_path_cached():
671767
defaultParams['datapath'][0]=_get_data_path()
672768
returndefaultParams['datapath'][0]
673769

674-
get_data_path=verbose.wrap('matplotlib data path %s',_get_data_path_cached,
675-
always=False)
770+
get_data_path=_wrap('matplotlib data path %s',_get_data_path_cached,
771+
always=False)
676772

677773

678774
defget_py2exe_datafiles():
@@ -1035,22 +1131,18 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
10351131
ifkeynotin_all_deprecated])
10361132
config.update(config_from_file)
10371133

1038-
verbose.set_level(config['verbose.level'])
1039-
verbose.set_fileo(config['verbose.fileo'])
1040-
10411134
ifconfig['datapath']isNone:
10421135
config['datapath']=get_data_path()
10431136

10441137
if"".join(config['text.latex.preamble']):
1045-
verbose.report("""
1138+
_log.info("""
10461139
*****************************************************************
10471140
You have the following UNSUPPORTED LaTeX preamble customizations:
10481141
%s
10491142
Please do not ask for support with these customizations active.
10501143
*****************************************************************
1051-
"""%'\n'.join(config['text.latex.preamble']),'helpful')
1052-
1053-
verbose.report('loaded rc file %s'%fname)
1144+
""",'\n'.join(config['text.latex.preamble']))
1145+
_log.info('loaded rc file %s',fname)
10541146

10551147
returnconfig
10561148

@@ -1736,9 +1828,7 @@ def inner(ax, *args, **kwargs):
17361828
returninner
17371829
returnparam
17381830

1739-
1740-
verbose.report('matplotlib version %s'%__version__)
1741-
verbose.report('verbose.level %s'%verbose.level)
1742-
verbose.report('interactive is %s'%is_interactive())
1743-
verbose.report('platform is %s'%sys.platform)
1744-
verbose.report('loaded modules: %s'%list(sys.modules),'debug')
1831+
_log.info('matplotlib version %s',__version__)
1832+
_log.info('interactive is %s',is_interactive())
1833+
_log.info('platform is %s',sys.platform)
1834+
_log.debug('loaded modules: %s',list(sys.modules))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp