Skip to content

Importing pyplot messes with command line argument parsing #1986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Nikratio opened this issue May 8, 2013 · 14 comments
Closed

Importing pyplot messes with command line argument parsing #1986

Nikratio opened this issue May 8, 2013 · 14 comments

Comments

@Nikratio
Copy link

Nikratio commented May 8, 2013

Consider this:

[0] nelarikon:~/tmp$ cat argparsebug.py
#!/usr/bin/env python

from __future__ import division, print_function, absolute_import
from argparse import ArgumentParser
import matplotlib
import matplotlib.pyplot as plt

parser = ArgumentParser()

parser.add_argument("--name", type=str, default=None,
                    help="Prefix for files to load")

options = parser.parse_args()
print('Name is %s' % repr(options.name))
print('matplotlib version:', matplotlib.__version__)
[0] nelarikon:~/tmp$ ./argparsebug.py --name foo
Name is None
matplotlib version: 1.2.0

Removing the import matplotlib.pyplot as plt line gives the correct output,

[0] nelarikon:~/tmp$ ./argparsebug.py --name foo
Name is 'foo'
matplotlib version: 1.2.0
@mdboom
Copy link
Member

mdboom commented May 8, 2013

The general recommendation is to parse all of your commandline arguments before importing matplotlib.

@WeatherGod
Copy link
Member

That would be news to me, and I think quite unintuitive and impractical as
some may not even realize they are importing matplotlib in the first place
(as a dependency to some other library). This is something that has
bothered me and I have made some strides to reduce the impact of
matplotlib's debugging flags.

Personally, I think we ought to embrace the logging framework and abolish
command-line handling altogether in mpl.

@mdboom
Copy link
Member

mdboom commented May 8, 2013

@WeatherGod: Sure, as a long term plan, we should reduce the commandline handling. Note, however, it isn't just for logging that mpl uses commandline flags. It also can be used to set the backend (which I personally use all the time).

@Nikratio
Copy link
Author

Nikratio commented May 8, 2013

@mdboom: Would it be possible to put that recommendation somewhere prominently? I've never heard of it before, and I couldn't find it in e.g. http://matplotlib.org/users/pyplot_tutorial.html either.

@mdboom
Copy link
Member

mdboom commented May 8, 2013

Yeah -- there isn't even a good place that documents what the commandline arguments are (it's sort of touched on in the FAQ).

I'm all for adding more info about this -- I'm not sure the pyplot tutorial is the right place. This is more about embedding matplotlib within a larger application.

@WeatherGod
Copy link
Member

I would argue that even controlling the backend selection should be done by
the script-maker. It is possible that we could make a function that makes
supplies an argparse argument to add that triggers a callback to setting
the backend, but I don't think matplotlib as a library should ever be
messing around with command line arguments.

I might be able to prototype such a argument.

@efiring
Copy link
Member

efiring commented May 8, 2013

On 2013/05/08 8:03 AM, Benjamin Root wrote:

I don't think matplotlib as a library should ever be
messing around with command line arguments.

I agree. Although it can be convenient, it seems like fundamentally bad
behavior. It is also obscure--which perhaps has the advantage now that
removing this behavior might be less painful than would be the case if
it had been better publicized and therefore more widely used.

@WeatherGod
Copy link
Member

Ok, here is a quick go at it:

import argparse

class BackendSwitcher(argparse.Action):
    """
    Set an instance of this class as an "action" to
    an argparse argument to enable backend switching.
    """
    def __call__(self, parser, namespace, values, option_string=None) :
        setattr(namespace, self.dest, values)
        matplotlib.use(values, warn=False, force=True)

@tacaswell tacaswell modified the milestones: v1.4.x, v1.4.0 Mar 24, 2014
@tacaswell tacaswell added the doc label Sep 5, 2014
@tacaswell tacaswell modified the milestones: v1.4.x, 1.5.0 Feb 7, 2015
@tacaswell tacaswell modified the milestones: Color overhaul, next point release Jul 17, 2015
@tacaswell
Copy link
Member

Should this fall under the color overhaul 2.0 breaking changes?

I am -0.5, am flagging it for discussion.

@efiring
Copy link
Member

efiring commented Jul 17, 2015

It seems like this needs to go through a deprecation cycle, unfortunately. Maybe the thing to do right away is add some documentation, including a warning that it will go away.

@mdboom mdboom modified the milestones: Color overhaul, next major release (2.0) Oct 8, 2015
@efiring
Copy link
Member

efiring commented Feb 15, 2016

This can no longer be reproduced, even on mpl 1.3.1, based on testing by @tacaswell. Evidently it was fixed some time in the misty past.

@efiring efiring closed this as completed Feb 15, 2016
@moonfriend
Copy link

moonfriend commented May 22, 2019

I have this issue with matplotlib 3.1.0 on python3. And you can imagine it takes quite a while until you recognize the problem is in a library which randomely decides to remove your input parameters!

@QuLogic
Copy link
Member

QuLogic commented May 22, 2019

There is no manipulation of sys.argv on 3.1.0.

@moonfriend
Copy link

moonfriend commented May 22, 2019

Yes you are right probably on python2

mo@m:~/tbin$ cat test_args.py
import sys
import matplotlib.pyplot as plt

if __name__ == '__main__':
    print(sys.argv)

The result is different between python2 and python3

mo@m:~/tbin$ python2 ./test_args.py --name foo
['./test_args.py', '--name', 'foo']

mo@m:~/tbin$ python3 ./test_args.py --name foo
['./test_args.py']

and it only happens for "--name" input argument

mo@m-:~/tbin$ python3 ./test_args.py --namex foo
['./test_args.py', '--namex', 'foo']

my current versions of matplotlib:

moghimim@m:~/tbin$  python2 -c "import matplotlib;print(matplotlib.__version__)"
2.2.4
mo@m:~/tbin$  python3 -c "import matplotlib;print(matplotlib.__version__)"
3.1.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants