15

I'm using Python's argparse module to parse command line arguments. Consider the following simplified example,

# File test.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-s', action='store')
parser.add_argument('-a', action='append')
args = parser.parse_args()
print(args)

which can successfully be called like

python test.py -s foo -a bar -a baz

A single argument is required after -s and after each -a, which may contain spaces if we use quotation. If however an argument starts with a dash (-) and does not contain any spaces, the code crashes:

python test.py -s -begins-with-dash -a bar -a baz

error: argument -s: expected one argument

I get that it interprets -begins-with-dash as the beginning of a new option, which is illegal as -s has not yet received its required argument. It's also pretty clear though that no option with the name -begins-with-dash has been defined, and so it should not interpret it as an option in the first place. How can I make argparse accept arguments with one or more leading dashes?

jmd_dk
  • 12,125
  • 9
  • 63
  • 94
  • Due to the `argparse` parsing approach it is hard, if not impossible, to do this. https://bugs.python.org/issue9334 – hpaulj Oct 03 '18 at 22:25
  • Possible duplicate of https://stackoverflow.com/questions/16174992/cant-get-argparse-to-read-quoted-string-with-dashes-in-it – hpaulj Oct 04 '18 at 01:07
  • Does this answer your question? [Can't get argparse to read quoted string with dashes in it?](https://stackoverflow.com/questions/16174992/cant-get-argparse-to-read-quoted-string-with-dashes-in-it) – Mihai Capotă Oct 22 '21 at 00:34

2 Answers2

26

You can force argparse to interpret an argument as a value by including an equals sign:

python test.py -s=-begins-with-dash -a bar -a baz
Namespace(a=['bar', 'baz'], s='-begins-with-dash')
Yevhen Kuzmovych
  • 10,940
  • 7
  • 28
  • 48
Joey Harrington
  • 291
  • 2
  • 3
  • 5
    True, though what I really want is a solution from within the Python script, allowing it to be called like `-s -begins-with-dash`. – jmd_dk Oct 03 '18 at 22:12
  • The equal sign is also limited to single value arguments (i.e. can't do this with nargs arguments). – ybenjira Mar 02 '23 at 00:00
2

If you are instead trying to provide multiple values to one argument:

parser.add_argument('-a', action='append', nargs=argparse.REMAINDER)

will grab everything after -a on the command line and shove it in a.

python test.py -toe -a bar fi -fo -fum -s fee -foo
usage: test.py [-h] [-s S] [-a ...]
test.py: error: unrecognized arguments: -toe

python test.py -a bar fi -fo -fum -s fee -foo
Namespace(a=[['bar', 'fi', '-fo', '-fum', '-s', 'fee', '-foo']], s=None)

Note that even though -s is a recognized argument, argparse.REMAINDER adds it to the list of args found by -a since it is after -a on the command line

jeremysprofile
  • 10,028
  • 4
  • 33
  • 53
  • Provided you have the flexibility of choosing which param goes where. This method also doesn't allow you to have two of these types of arguments in one command line. – ybenjira Mar 02 '23 at 00:03