Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

argparse: optional argument as flag and variable

I'm writing a program that takes two argument (paths) and as an option -l, witch enables save the log in a log file.

I'm using argparse and create the following argument:

parser.add_argument('-l', '--logfile', 
                    nargs='?', 
                    const='tranfer.log', 
                    default=False,
                    help='save log of the transfer')

These are the forms of use:

  1. prog.py path_1 path_2. Nothing special.
  2. prog.py -l filename path_1 path_2. Save the log in filename file.
  3. prog.py -l path_1 path_2. Save the log the file by default (say, logfile).

I have a problem in item 3, because prog.py takes path_1 as the filename of the log file. The issue was easily fixed puttin -l option at the end of the line.

prog.py path_1 path_2 -l

But I was wondering if there's a way of tell argparse to use the last two option as the path files, because I'll be not the only one who use the program.

Path argument were add as follows:

parser.add_argument('left_path', 
                    action='store',
                    help='first path')
parser.add_argument('right_path', 
                    action='store',
                    help='second path')
like image 417
fferrin Avatar asked Oct 16 '25 14:10

fferrin


1 Answers

Your assessment is right,

prog.py -l path_1 path_2

will assign path_1 to l and path_2 to the first positional, and raise an error about missing 2nd positional.

http://bugs.python.org/issue9338 argparse optionals with nargs='?', '*' or '+' can't be followed by positionals is a bug/issue that deals with this. Patches have been proposed, but not implemented. It's not trivial. When handing -l the parser would have to look ahead to see how many arguments are needed to satisfy the positionals, and refrain from consuming the next string (even though by your definition it has every right to do so).

It's also been discussed in previous SO questions.

https://stackoverflow.com/a/29853186/901925

https://stackoverflow.com/a/26986546/901925

You have to either put the optional last, or use some other means of signaling the end of its list of arguments (-- or other flagged optional). Or change the argument definitions, so that -l is not ? (or the equivalent), or change the positionals to flagged.

like image 179
hpaulj Avatar answered Oct 19 '25 06:10

hpaulj