Reputation: 89946
I have a command-line option that requires an argument. I would like to be able to supply "--"
as the argument, but I can't figure out how to do it.
Sample code: (test-argparse.py
)
#!/usr/bin/env python
from __future__ import print_function
import argparse
import sys
def main(argv):
ap = argparse.ArgumentParser()
ap.add_argument("-x", "--foo", metavar="VALUE", default="",
help="Test option.")
args = ap.parse_args(argv[1:])
print(args.foo)
if __name__ == "__main__":
sys.exit(main(sys.argv))
All my attempts to try to pass "--"
as an argument fail:
$ test-argparse.py --foo --
usage: test-argparse.py [-h] [-x VALUE]
test-argparse.py: error: argument -x/--foo: expected one argument
$ test-argparse.py --foo -- --
usage: test-argparse.py [-h] [-x VALUE]
test-argparse.py: error: argument -x/--foo: expected one argument
$ test-argparse.py --foo=--
[]
$ test-argparse.py --foo=-- --
usage: test-argparse.py [-h] [-x VALUE]
test-argparse.py: error: unrecognized arguments: --
$ test-argparse.py --foo="--"
[]
$ test-argparse.py '--foo --'
usage: test-argparse.py [-h] [-x VALUE]
test-argparse.py: error: unrecognized arguments: --foo --
$ test-argparse.py -x--
[]
$ test-argparse.py '-x --'
--
The last case is the closest, but it includes the space (and I can't just strip whitespace, because what if I want to allow " "
as a value?). Is there any way that I can accomplish this?
That argparse forces argument permutation on clients (leading to unnecessary ambiguity) is very frustrating.
(I am using Python 2.7.12.)
Upvotes: 2
Views: 888
Reputation: 231355
Ideally --foo=--
should work, but the current parser deletes all '--', leaving an empty string in its place, hence the foo=[]
result. I proposed a patch a couple of years ago that should have fixed that, but it's caught in the argparse
backlog. http://bugs.python.org/issue13922, http://bugs.python.org/issue14364, http://bugs.python.org/issue9571
Python argparse with -- as the value suggests preprocessing sys.argv
replacing one or more of the --
with something else.
If you are game for patching your argparse.py
file (or subclass the ArgumentParser
class), I could revisit my earlier work and suggest a fix. The trick is to accept that =--
but still use the first free --
as the 'rest-are-positionals' flag (and retain any following --
). Unfortunately one method that needs to be patched is nested in a much larger one.
Upvotes: 2
Reputation: 249123
There is a specific reason that this doesn't work: --
means "Skip this token and consider the rest of the arguments to be positional, even if they start with a dash."
Many, many programs won't accept --
as an argument, but they will accept -
. The single dash is even a standard way of specifying "Use standard input or output" in place of a filename.
So the best thing you can do for the users of your program is probably to not design it to require --
, because that's not something that's usually done, and not something that most modern command-line parsing libraries are likely able to parse.
You could use --
as a positional option, so you could probably support this:
--foo -- --
If you make --foo
have action='store_true'
(i.e. it is an option taking no argument), plus one non-mandatory positional argument. That will probably work, because the first --
means "stop processing dashes as options" and the second is a positional argument.
Upvotes: 1