Can't get argparse to read quoted string with dashes in it?

sfendell picture sfendell · Apr 23, 2013 · Viewed 26k times · Source

Is there a way to make argparse recognize anything between two quotes as a single argument? It seems to keep seeing the dashes and assuming that it's the start of a new option

I have something like:

mainparser = argparse.ArgumentParser()
subparsers = mainparser.add_subparsers(dest='subcommand')
parser = subparsers.add_parser('queue')
parser.add_argument('-env', '--extraEnvVars', type=str,
                        help='String of extra arguments to be passed to model.')
...other arguments added to parser...

But when I run:

python Application.py queue -env "-s WHATEVER -e COOL STUFF"

It gives me:

Application.py queue: error: argument -env/--extraEnvVars: expected one argument

If I leave off the first dash, it works totally fine, but it's kind of crucial that I be able to pass in a string with dashes in it. I've tried escaping it with \ , which causes it to succeed but adds the \ to the argument string Does anyone know how to get around this? This happens whether or not -s is an argument in parser.

EDIT: I'm using Python 2.7.

EDIT2:

python Application.py -env " -env"

works perfectly fine, but

python Application.py -env "-env"

does not.

EDIT3: Looks like this is actually a bug that's being debated already: http://www.gossamer-threads.com/lists/python/bugs/89529, http://python.6.x6.nabble.com/issue9334-argparse-does-not-accept-options-taking-arguments-beginning-with-dash-regression-from-optp-td578790.html. It's only in 2.7 and not in optparse.

EDIT4: The current open bug report is: http://bugs.python.org/issue9334

Answer

SethMMorton picture SethMMorton · Apr 23, 2013

Updated answer:

You can put an equals sign when you call it:

python Application.py -env="-env"

Original answer:

I too have had troubles doing what you are trying to do, but there is a workaround build into argparse, which is the parse_known_args method. This will let all arguments that you haven't defined pass through the parser with the assumption that you would use them for a subprocess. The drawbacks are that you won't get error reporting with bad arguments, and you will have to make sure that there is no collision between your options and your subprocess's options.

Another option could be to force the user's to use a plus instead of a minus:

python Application.py -e "+s WHATEVER +e COOL STUFF"

and then you change the '+' to '-' in post processing before passing to your subprocess.