Reputation: 346
I am trying to parse some options with argparse. I have found some similar problems discussed and found what I thought was a similar issue with a sensible solution given by Owen in Options with Options with Python argparse?
I want to be able to specify, for example:
script.py infile --line <path to file1> beglab='str1' endlab='str2'
--line <path to file2>
--line <path to file3> beglab='str3'
outfile
--line can be specified multiple times. Initially I had no extra arguments for the line option and I was able to create a list of the files without a problem using:
parser.add_argument("--line", action='append')
Now I need to optionally add labels to go with the lines. There can be 0, 1 or 2 labels associated with a given line as shown above. This is why I felt the example in the link provided seemed appropriate, unfortunately when I try:
parser.add_argument("--line", action='append', nargs="+")
And run:
script.py infile --line somefile beglab='A' endlab='B'
--line otherfile beglab='a' endlab='b' outfile
or
script.py infile --line somefile outfile
I get an error stating that there are too few arguments. If I remove the --line options from the command so I have just the positional ones, it works, so I know I haven't missed anything required. So I went and I read up on the nargs options. If --line is specified, it must have at least the filename, therefore I think that nargs='+'
is the appropriate option, it looks about right in the help [--line LINE [LINE ...]]
, so I am really confused about where this error has come from.
I am happy to consider alternative methods of dealing with this, I just liked the simplicity of providing the inputs like this and creating a dictionary with them.
Upvotes: 3
Views: 606
Reputation: 168626
The parser you want to build is ambiguous. If endlab='b'
is optional, then argparse can't tell if the operator intends that outfile
is a parameter to --line
or a positional argument.
You don't have to change your parser, but you do have to change your command line:
Try:
script.py infile outfile
--line somefile beglab='A' endlab='B'
--line otherfile beglab='a' endlab='b'
Or:
script.py infile
--line somefile beglab='A' endlab='B'
--line otherfile beglab='a' endlab='b'
--
outfile
Upvotes: 2
Reputation: 3189
I'm not sure about how to accomplish this with argparse, but for simplicity, I would consider doing something like:
--line <path_to_file>,<beglab>,<endlab>
And then parse the argument either in code or using argparse's custom type functionality. You can have the custom type function return a dict like {'filepath':'<path_to_file>', 'beglab':'<beglab>', 'endlab':'<endlab>'}
Upvotes: 0