Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optional positional arguments with Python's argparse

Trying to parse optional positional arguments I ran into following issue:

Example:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('infile')
parser.add_argument('outfile', nargs='?')
parser.add_argument('-v', action='store_true')

print(parser.parse_args())

Output:

$ ./x.py -v in out
Namespace(infile='in', outfile='out', v=True)

$ ./x.py in out -v
Namespace(infile='in', outfile='out', v=True)

$ ./x.py in -v out
usage: x.py [-h] [-v] infile [outfile]
x.py: error: unrecognized arguments: out

Why is the third program invocation not accepted? Is this a restriction of argparse?

like image 328
Andreas Matthias Avatar asked Jul 07 '18 21:07

Andreas Matthias


People also ask

How do you make an argument mandatory in Python?

If a user is required to make an argument, they can set the keyword argument required to True .

What does Store_true mean?

2. I would add this: store_true means if true was specified then set param value but otherwise leave it to None. If default was also specified then param is set to that value instead of leaving it to None.

How do you give Argparse optional arguments in Python?

After importing the library, argparse. ArgumentParser() initializes the parser so that you can start to add custom arguments. To add your arguments, use parser. add_argument() .

What are positional arguments in Python?

Positional arguments are arguments that need to be included in the proper position or order. The first positional argument always needs to be listed first when the function is called. The second positional argument needs to be listed second and the third positional argument listed third, etc.


1 Answers

This is a limitation of argparse—but one that's partially lifted in 3.7.

Unix tools generally don't claim to support intermixing of options and arguments, even though they often do. The problem is that combining it with some other features, like subcommands, leads to ambiguity. So, typically, libraries that support any of those features punt on the problem and don't allow intermixing. Or they do something kind of hacky—allowing options at the end, at the start, and in certain hard-to-predict cases but not others in the middle.

That's what argparse originally did. But 3.7 adds Intermixed parsing.

You have to manually call parse_intermixed_args instead of parse_args.

And if you try to use this with any of the features it doesn't go well with, you'll get an exception (even if there's no ambiguity for the particular set of args you pass—which should make it easier to debug).

But otherwise, it'll work as expected: options (together with their values, of course) can be freely mixed with positional arguments anywhere in the command line.


Unfortunately, I don't know of a drop-in backport on PyPI to get 3.7 argparse in earlier versions; the semi-official argparse backport is mainly for pre-2.7/3.2 versions that don't have it at all, and only backports the 3.4 version.

like image 87
abarnert Avatar answered Oct 14 '22 04:10

abarnert