1

I create the following argument parser:

parser = argparse.ArgumentParser()
parser.add_argument('name')
parser.add_argument('script')
parser.add_argument('--src', nargs='?')

When running ./script.py the_name the_script --src my_script.py, all the arguments get their value "as expected".

Now, I add a remainder:

parser = argparse.ArgumentParser()
parser.add_argument('name')
parser.add_argument('script')
parser.add_argument('--src', nargs='?')
parser.add_argument('args', nargs=argparse.REMAINDER)

Now, running again ./script.py the_name the_script --src my_script.py, argument src suddenly becomes None.

However, running ./script.py --src my_script.py the_name the_script --arg1 arg2 xyz will set all arguments "as expected".

How can I achieve that my argument parser first wants to see the positional arguments name and script, then some known arguments like --src and then finally an arbitrary remainder?

Michael
  • 7,407
  • 8
  • 41
  • 84
  • Possible duplicate of [Python argparse ignore unrecognised arguments](https://stackoverflow.com/questions/12818146/python-argparse-ignore-unrecognised-arguments) – ti7 Jun 26 '19 at 19:28

2 Answers2

0
parser.add_argument('args', nargs='+')

But then you have to always provide at least one args argument.

print parser.parse_args('--src 12 1 2 3 4'.split())
print parser.parse_args('1 2 --src 12 3 4'.split())

Output:

Namespace(args=['3', '4'], name='1', script='2', src='12')
Namespace(args=['3', '4'], name='1', script='2', src='12')

Doesn't work with nargs='*', alas:

parser.add_argument('args', nargs='*')

print parser.parse_args('--src 12 1 2 3 4'.split())
print parser.parse_args('1 2 --src 12 3 4'.split())

Output:

Namespace(args=['3', '4'], name='1', script='2', src='12')
usage: argp.py [-h] [--src SRC] name script [args [args ...]]
argp.py: error: unrecognized arguments: 3 4

I.e. --src 12 1 2 3 4 works but 1 2 --src 12 3 4 doesn't.

phd
  • 82,685
  • 13
  • 120
  • 165
0

Looks like your question is very similar to the example used in the end of section "15.4.3.3. nargs" in Python's official docs.

Seems like the answer to your problem is to put --src as the first parameter, before the positional ones.

I did the following and it seems to work:

parser = argparse.ArgumentParser()
parser.add_argument('--src')
parser.add_argument('name')
parser.add_argument('script')
parser.add_argument('args', nargs=argparse.REMAINDER)

When I run the above script like using ./script.py --src=my_script.py the_name the_script 1 2 3 the result is, as expected:

name = the_name
script = the_script
src = my_script.py
args = ['1', '2', '3']

If I remove the --src like ./script.py the_name the_script 1 2 3 the result is:

name = the_name
script = the_script
src = None
args = ['1', '2', '3']`

Naturally I can keep the --src and omit the 1 2 3 parameters, thus if I run ./script.py --src=my_script.py the_name the_script the result is:

name = the_name
script = the_script
src = my_script.py
args = []`

Which looks like what you'll expect.

gmauch
  • 1,316
  • 4
  • 25
  • 39