matplotlib.use()

Hi,

I'm here at the SciPy sprints trying to fix switching inline/gui for
the ipython notebook. I've noticed something weird about
matplotlib.use() :

    if 'matplotlib.backends' in sys.modules:
        if warn: warnings.warn(_use_error_msg)
        return
    if arg.startswith('module://'):
        name = arg
    else:
        # Lowercase only non-module backend names (modules are case-sensitive)
        arg = arg.lower()
        name = validate_backend(arg)
    rcParams['backend'] = name

Notice the return if it finds the module loaded. This return basically
makes it impossible to make use() have any effect one backends has
been loaded. However, matplotlib.pyplot.switch_backend(). Eric added
this in 2008 as a bug fix, but no more detail than that. Does anyone
have a problem putting the return with the warning? Therefore if you
pass warn=False, you can actually make the setting take effect, but
the average user won't accidentally shoot their foot off. Something
like:

    if 'matplotlib.backends' in sys.modules:
        if warn:
            warnings.warn(_use_error_msg)
            return

Ryan

···

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Hi,

I'm here at the SciPy sprints trying to fix switching inline/gui for
the ipython notebook. I've noticed something weird about
matplotlib.use() :

     if 'matplotlib.backends' in sys.modules:
         if warn: warnings.warn(_use_error_msg)
         return
     if arg.startswith('module://'):
         name = arg
     else:
         # Lowercase only non-module backend names (modules are case-sensitive)
         arg = arg.lower()
         name = validate_backend(arg)
     rcParams['backend'] = name

Notice the return if it finds the module loaded. This return basically
makes it impossible to make use() have any effect one backends has
been loaded. However, matplotlib.pyplot.switch_backend(). Eric added
this in 2008 as a bug fix, but no more detail than that. Does anyone
have a problem putting the return with the warning? Therefore if you
pass warn=False, you can actually make the setting take effect, but
the average user won't accidentally shoot their foot off. Something
like:

     if 'matplotlib.backends' in sys.modules:
         if warn:
             warnings.warn(_use_error_msg)
             return

This would be defeating the basic idea: use() is *only* designed to take effect *once*. If you need to switch backends, it takes more than what use() does, hence the need for switch_backend(). (But see below.)

The warn=False invocation of use, with the return statement were it is now, is for the case where you may have a script or module that specifies a backend (in case it is the first or only import of matplotlib), but that may itself be imported or called by something else that has already imported matplotlib and set the backend. In this case we want the warning to be suppressed, which is all the warn=False flag is supposed to do. I use this myself.

So it looks like the problem is that switch_backends is broken because what it needs matplotlib.use to do is go ahead and make the switch. This could be done by adding a force=True kwarg (default would be False) to matplotlib.use, or by deleting the reference to the backends module from sys.modules in switch_backends before calling matplotlib.use. A variation would be to use the force kwarg and to include the switch_backends logic, or at least the reload line, in matplotlib.use. That probably makes sense: add the force kwarg, and when the module is replaced, reload it immediately within matplotlib.use. Then pyplot.switch_backends only needs to do the pyplot-specific operations. I think that is the cleanest solution.

Eric

···

On 2012/07/20 9:34 AM, Ryan May wrote:

Ryan

I like the “force” idea very much. It means exactly what it says.

Ben Root

···

On Fri, Jul 20, 2012 at 3:20 PM, Eric Firing <efiring@…229…> wrote:

On 2012/07/20 9:34 AM, Ryan May wrote:

Hi,

I’m here at the SciPy sprints trying to fix switching inline/gui for

the ipython notebook. I’ve noticed something weird about

matplotlib.use() :

 if 'matplotlib.backends' in sys.modules:
     if warn: warnings.warn(_use_error_msg)
     return
 if arg.startswith('module://'):
     name = arg
 else:
     # Lowercase only non-module backend names (modules are case-sensitive)
     arg = arg.lower()
     name = validate_backend(arg)
 rcParams['backend'] = name

Notice the return if it finds the module loaded. This return basically

makes it impossible to make use() have any effect one backends has

been loaded. However, matplotlib.pyplot.switch_backend(). Eric added

this in 2008 as a bug fix, but no more detail than that. Does anyone

have a problem putting the return with the warning? Therefore if you

pass warn=False, you can actually make the setting take effect, but

the average user won’t accidentally shoot their foot off. Something

like:

 if 'matplotlib.backends' in sys.modules:
     if warn:
         warnings.warn(_use_error_msg)
         return

This would be defeating the basic idea: use() is only designed to take

effect once. If you need to switch backends, it takes more than what

use() does, hence the need for switch_backend(). (But see below.)

The warn=False invocation of use, with the return statement were it is

now, is for the case where you may have a script or module that

specifies a backend (in case it is the first or only import of

matplotlib), but that may itself be imported or called by something else

that has already imported matplotlib and set the backend. In this case

we want the warning to be suppressed, which is all the warn=False flag

is supposed to do. I use this myself.

So it looks like the problem is that switch_backends is broken because

what it needs matplotlib.use to do is go ahead and make the switch. This

could be done by adding a force=True kwarg (default would be False) to

matplotlib.use, or by deleting the reference to the backends module from

sys.modules in switch_backends before calling matplotlib.use. A

variation would be to use the force kwarg and to include the

switch_backends logic, or at least the reload line, in matplotlib.use.

That probably makes sense: add the force kwarg, and when the module is

replaced, reload it immediately within matplotlib.use. Then

pyplot.switch_backends only needs to do the pyplot-specific operations.

I think that is the cleanest solution.

Eric

I agree, this is a better way to go. (And occurred to me as well after
the initial PR.)

Glad I asked rather than doing my 2-line fix. The updated PR is at

Ryan

···

On Fri, Jul 20, 2012 at 3:20 PM, Eric Firing <efiring@...229...> wrote:

This would be defeating the basic idea: use() is *only* designed to take
effect *once*. If you need to switch backends, it takes more than what
use() does, hence the need for switch_backend(). (But see below.)

The warn=False invocation of use, with the return statement were it is
now, is for the case where you may have a script or module that
specifies a backend (in case it is the first or only import of
matplotlib), but that may itself be imported or called by something else
that has already imported matplotlib and set the backend. In this case
we want the warning to be suppressed, which is all the warn=False flag
is supposed to do. I use this myself.

So it looks like the problem is that switch_backends is broken because
what it needs matplotlib.use to do is go ahead and make the switch. This
could be done by adding a force=True kwarg (default would be False) to
matplotlib.use, or by deleting the reference to the backends module from
sys.modules in switch_backends before calling matplotlib.use. A
variation would be to use the force kwarg and to include the
switch_backends logic, or at least the reload line, in matplotlib.use.
That probably makes sense: add the force kwarg, and when the module is
replaced, reload it immediately within matplotlib.use. Then
pyplot.switch_backends only needs to do the pyplot-specific operations.
  I think that is the cleanest solution.

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma