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

Commite8f0b22

Browse files
committed
backend switching.
See changes documented in the API changes file.Some followup cleanup (of the now unused old machinery) will come as aseparate PR (left some "FIXME: Remove." comments).Changes to the build process (namely, getting rid of trying to detectthe default backend in setupext.py) will come as a separate PR.I inlined pylab_setup into switch_backend (and deprecated the oldversion of pylab_setup) because otherwise the typical call stack wouldbe `use()` -> `set rcParams['backend'] = ...` -> `switch_backend()` ->`pylab_setup()`, which is a bit of a mess; at least we can get rid ofone of the layers.
1 parent4fc9288 commite8f0b22

File tree

8 files changed

+152
-89
lines changed

8 files changed

+152
-89
lines changed

‎doc/api/next_api_changes/2018-02-15-AL-deprecations.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The following classes, methods, functions, and attributes are deprecated:
1818
- ``backend_ps.get_bbox``,
1919
- ``backend_qt5.error_msg_qt``, ``backend_qt5.exception_handler``,
2020
- ``backend_wx.FigureCanvasWx.macros``,
21+
- ``backends.pylab_setup``,
2122
- ``cbook.GetRealpathAndStat``, ``cbook.Locked``,
2223
- ``cbook.is_numlike`` (use ``isinstance(..., numbers.Number)`` instead),
2324
``cbook.listFiles``, ``cbook.unicode_safe``,

‎doc/api/next_api_changes/2018-06-27-AL.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
Changes to backend loading
22
``````````````````````````
33

4+
Assignment to ``rcParams["backend"]`` now sets the backend. Backends can now
5+
be switched until a figure is actually created.
6+
47
Failure to load backend modules (``macosx`` on non-framework builds and
58
``gtk3`` when running headless) now raises `ImportError` (instead of
69
`RuntimeError` and `TypeError`, respectively.

‎lib/matplotlib/__init__.py

Lines changed: 14 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,7 @@ def __exit__(self, exc_type, exc_value, exc_tb):
13171317
dict.update(rcParams,self._orig)
13181318

13191319

1320+
# FIXME: Remove.
13201321
_use_error_msg="""
13211322
This call to matplotlib.use() has no effect because the backend has already
13221323
been chosen; matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
@@ -1329,62 +1330,23 @@ def __exit__(self, exc_type, exc_value, exc_tb):
13291330

13301331
defuse(arg,warn=True,force=False):
13311332
"""
1332-
Set thematplotlib backend to one of the known backends.
1333+
Set theMatplotlib backend.
13331334
1334-
The argument is case-insensitive. *warn* specifies whether a
1335-
warning should be issued if a backend has already been set up.
1336-
*force* is an **experimental** flag that tells matplotlib to
1337-
attempt to initialize a new backend by reloading the backend
1338-
module.
1335+
The argument is case-insensitive. Switching to an interactive backend is
1336+
only safe if no event loop for another interactive backend has started.
1337+
Switching to and from non-interactive backends is safe.
13391338
1340-
.. note::
1341-
1342-
This function must be called *before* importing pyplot for
1343-
the first time; or, if you are not using pyplot, it must be called
1344-
before importing matplotlib.backends. If warn is True, a warning
1345-
is issued if you try and call this after pylab or pyplot have been
1346-
loaded. In certain black magic use cases, e.g.
1347-
:func:`pyplot.switch_backend`, we are doing the reloading necessary to
1348-
make the backend switch work (in some cases, e.g., pure image
1349-
backends) so one can set warn=False to suppress the warnings.
1350-
1351-
To find out which backend is currently set, see
1352-
:func:`matplotlib.get_backend`.
1339+
To find out which backend is currently set, see `matplotlib.get_backend`.
13531340
1341+
Parameters
1342+
----------
1343+
arg : str
1344+
The name of the backend to use.
13541345
"""
1355-
# Lets determine the proper backend name first
1356-
ifarg.startswith('module://'):
1357-
name=arg
1358-
else:
1359-
# Lowercase only non-module backend names (modules are case-sensitive)
1360-
arg=arg.lower()
1361-
name=validate_backend(arg)
1362-
1363-
# Check if we've already set up a backend
1364-
if'matplotlib.backends'insys.modules:
1365-
# Warn only if called with a different name
1366-
if (rcParams['backend']!=name)andwarn:
1367-
importmatplotlib.backends
1368-
warnings.warn(
1369-
_use_error_msg.format(
1370-
backend=rcParams['backend'],
1371-
tb=matplotlib.backends._backend_loading_tb),
1372-
stacklevel=2)
1373-
1374-
# Unless we've been told to force it, just return
1375-
ifnotforce:
1376-
return
1377-
need_reload=True
1378-
else:
1379-
need_reload=False
1380-
1381-
# Store the backend name
1382-
rcParams['backend']=name
1383-
1384-
# If needed we reload here because a lot of setup code is triggered on
1385-
# module import. See backends/__init__.py for more detail.
1386-
ifneed_reload:
1387-
importlib.reload(sys.modules['matplotlib.backends'])
1346+
# We want to keep 'use(...); rcdefaults()' working, which means that
1347+
# use(...) needs to force the default backend too.
1348+
rcParams["backend"]= \
1349+
rcParamsDefault["backend"]=rcParamsOrig["backend"]=arg
13881350

13891351

13901352
ifos.environ.get('MPLBACKEND'):

‎lib/matplotlib/backend_bases.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3210,6 +3210,10 @@ class _Backend(object):
32103210
# class FooBackend(_Backend):
32113211
# # override the attributes and methods documented below.
32123212

3213+
# Set to one of {"qt5", "qt4", "gtk3", "wx", "tk", "macosx"} if an
3214+
# interactive framework is required, or None otherwise.
3215+
required_interactive_framework=None
3216+
32133217
# `backend_version` may be overridden by the subclass.
32143218
backend_version="unknown"
32153219

@@ -3292,7 +3296,8 @@ def show(cls, block=None):
32923296

32933297
@staticmethod
32943298
defexport(cls):
3295-
fornamein ["backend_version",
3299+
fornamein ["required_interactive_framework",
3300+
"backend_version",
32963301
"FigureCanvas",
32973302
"FigureManager",
32983303
"new_figure_manager",

‎lib/matplotlib/backends/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
importtraceback
66

77
importmatplotlib
8+
frommatplotlibimportcbook
89
frommatplotlib.backend_basesimport_Backend
910

1011
_log=logging.getLogger(__name__)
1112

1213
backend=matplotlib.get_backend()
14+
# FIXME: Remove.
1315
_backend_loading_tb="".join(
1416
lineforlineintraceback.format_stack()
1517
# Filter out line noise from importlib line.
@@ -64,6 +66,7 @@ def _get_running_interactive_framework():
6466
returnNone
6567

6668

69+
@cbook.deprecated("3.0")
6770
defpylab_setup(name=None):
6871
"""
6972
Return new_figure_manager, draw_if_interactive and show for pyplot.

‎lib/matplotlib/pyplot.py

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
The object-oriented API is recommended for more complex plots.
1919
"""
2020

21+
importimportlib
2122
importinspect
23+
importlogging
2224
fromnumbersimportNumber
2325
importre
2426
importsys
@@ -29,7 +31,7 @@
2931
importmatplotlib
3032
importmatplotlib.colorbar
3133
importmatplotlib.image
32-
frommatplotlibimportstyle
34+
frommatplotlibimportrcsetup,style
3335
frommatplotlibimport_pylab_helpers,interactive
3436
frommatplotlib.cbookimport (
3537
dedent,deprecated,silent_list,warn_deprecated,_string_to_bool)
@@ -67,10 +69,13 @@
6769
MaxNLocator
6870
frommatplotlib.backendsimportpylab_setup
6971

72+
_log=logging.getLogger(__name__)
73+
7074

7175
## Backend detection ##
7276

7377

78+
# FIXME: Deprecate.
7479
def_backend_selection():
7580
"""
7681
If rcParams['backend_fallback'] is true, check to see if the
@@ -110,8 +115,6 @@ def _backend_selection():
110115
## Global ##
111116

112117

113-
_backend_mod,new_figure_manager,draw_if_interactive,_show=pylab_setup()
114-
115118
_IP_REGISTERED=None
116119
_INSTALL_FIG_OBSERVER=False
117120

@@ -213,21 +216,60 @@ def findobj(o=None, match=None, include_self=True):
213216

214217
defswitch_backend(newbackend):
215218
"""
216-
Switch the default backend. This feature is **experimental**, and
217-
is only expected to work switching to an image backend. e.g., if
218-
you have a bunch of PostScript scripts that you want to run from
219-
an interactive ipython session, you may want to switch to the PS
220-
backend before running them to avoid having a bunch of GUI windows
221-
popup. If you try to interactively switch from one GUI backend to
222-
another, you will explode.
219+
Close all open figures and set the Matplotlib backend.
223220
224-
Calling this command will close all open windows.
221+
The argument is case-insensitive. Switching to an interactive backend is
222+
possible only if no event loop for another interactive backend has started.
223+
Switching to and from non-interactive backends is always possible.
224+
225+
Parameters
226+
----------
227+
newbackend : str
228+
The name of the backend to use.
225229
"""
226-
close('all')
230+
close("all")
231+
232+
ifnewbackendisrcsetup._auto_backend_sentinel:
233+
forcandidatein ["macosx","qt5agg","qt4agg","gtk3agg","gtk3cairo",
234+
"tkagg","wxagg","agg","cairo"]:
235+
try:
236+
switch_backend(candidate)
237+
exceptImportError:
238+
continue
239+
else:
240+
return
241+
242+
backend_name= (
243+
newbackend[9:]ifnewbackend.startswith("module://")
244+
else"matplotlib.backends.backend_{}".format(newbackend.lower()))
245+
246+
backend_mod=importlib.import_module(backend_name)
247+
Backend=type(
248+
"Backend", (matplotlib.backends._Backend,),vars(backend_mod))
249+
_log.info("Loaded backend %s version %s.",
250+
newbackend,Backend.backend_version)
251+
252+
required_framework=Backend.required_interactive_framework
253+
current_framework= \
254+
matplotlib.backends._get_running_interactive_framework()
255+
if (current_frameworkandrequired_framework
256+
andcurrent_framework!=required_framework):
257+
raiseImportError(
258+
"Cannot load backend {!r} which requires the {!r} interactive "
259+
"framework, as {!r} is currently running".format(
260+
newbackend,required_framework,current_framework))
261+
262+
dict.__setitem__(rcParams,"backend",newbackend)# Don't recurse.
263+
227264
global_backend_mod,new_figure_manager,draw_if_interactive,_show
228-
matplotlib.use(newbackend,warn=False,force=True)
229-
frommatplotlib.backendsimportpylab_setup
230-
_backend_mod,new_figure_manager,draw_if_interactive,_show=pylab_setup()
265+
_backend_mod=backend_mod
266+
new_figure_manager=Backend.new_figure_manager
267+
draw_if_interactive=Backend.draw_if_interactive
268+
_show=Backend.show
269+
270+
# Need to keep a global reference to the backend for compatibility reasons.
271+
# See https://github.com/matplotlib/matplotlib/issues/6092
272+
matplotlib.backends.backend=newbackend
231273

232274

233275
defshow(*args,**kw):
@@ -2358,6 +2400,9 @@ def _autogen_docstring(base):
23582400
# to determine if they should trigger a draw.
23592401
install_repl_displayhook()
23602402

2403+
# Set up the backend.
2404+
switch_backend(rcParams["backend"])
2405+
23612406

23622407
################# REMAINING CONTENT GENERATED BY boilerplate.py ##############
23632408

‎lib/matplotlib/rcsetup.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
parameter set listed here should also be visited to the
1414
:file:`matplotlibrc.template` in matplotlib's root source directory.
1515
"""
16+
1617
fromcollectionsimportIterable,Mapping
1718
fromfunctoolsimportreduce
1819
importoperator
1920
importos
2021
importre
22+
importsys
2123

2224
frommatplotlibimportcbook
2325
frommatplotlib.cbookimportls_mapper
@@ -242,13 +244,17 @@ def validate_fonttype(s):
242244

243245
_validate_standard_backends=ValidateInStrings(
244246
'backend',all_backends,ignorecase=True)
247+
_auto_backend_sentinel=object()
245248

246249

247250
defvalidate_backend(s):
248-
ifs.startswith('module://'):
249-
returns
250-
else:
251-
return_validate_standard_backends(s)
251+
backend= (
252+
sifsis_auto_backend_sentinelors.startswith("module://")
253+
else_validate_standard_backends(s))
254+
pyplot=sys.modules.get("matplotlib.pyplot")
255+
ifpyplot:
256+
pyplot.switch_backend(backend)
257+
returnbackend
252258

253259

254260
defvalidate_qt4(s):
@@ -965,9 +971,8 @@ def _validate_linestyle(ls):
965971

966972
# a map from key -> value, converter
967973
defaultParams= {
968-
'backend': ['Agg',validate_backend],# agg is certainly
969-
# present
970-
'backend_fallback': [True,validate_bool],# agg is certainly present
974+
'backend': [_auto_backend_sentinel,validate_backend],
975+
'backend_fallback': [True,validate_bool],
971976
'backend.qt4': [None,validate_qt4],
972977
'backend.qt5': [None,validate_qt5],
973978
'webagg.port': [8988,validate_int],

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp