Reputation: 57
I'm using this lib for parsing arguments in python : https://docs.python.org/2/library/argparse.html
So far I have this:
prog arg1 [-s arg2 [arg2 ...]] [-m arg3 [arg3 ...]]
And I want this:
prog arg1 -s arg2 [arg2 ...] -m arg3 [arg3 ...]
Here is my python code:
parser = argparse.ArgumentParser()
parser.add_argument('path', type=str,
help="path used for the generation of the rouge files")
parser.add_argument('-s', '--systems', type=str, nargs='+',
help="path to the systems generated summary files")
parser.add_argument('-m', '--models', type=str, nargs='+',
help="path to the reference summary files")
args = parser.parse_args()
print args
The problem is when you call the program without the optional arguments, it doesn't give an error (too few arguments). I want my optional arguments to be obligatory, but when you make the following call, the parser doesn't figure out which kind of args are involved...
For exemple with the following code:
parser = argparse.ArgumentParser()
parser.add_argument('arg1', type=str, nargs='+')
parser.add_argument('arg2', type=str, nargs='+')
parser.add_argument('arg3', type=str, nargs='+')
args = parser.parse_args()
And the following call:
python test.py arg1 arg1 arg1 arg2 arg2 arg3 arg3
I got this:
Namespace(arg1=['arg1', 'arg1', 'arg1', 'arg2', 'arg2'], arg2=['arg3'], arg3=['arg3'])
For sure here is the format of this prog:
prog arg1 [arg1 ...] arg2 [arg2 ...] arg3
Thanks for the help :)
Upvotes: 1
Views: 3303
Reputation: 231355
optionals
can take a required=True
parameter. That may be all you need.
p=argparse.ArgumentParser()
p.add_argument('-m',nargs='+',required=True)
p.add_argument('-n',nargs='+',required=True)
p.print_usage()
producing
usage: ipython3 [-h] -m M [M ...] -n N [N ...]
As to why:
Namespace(arg1=['arg1', 'arg1', 'arg1', 'arg2', 'arg2'], arg2=['arg3'], arg3=['arg3'])
you specified that each of arg1, arg2, arg3
required 1 or more strings. It split up the long list accordingly, giving arg2
and arg3
each one (which satisfies their requirement), and allocating the rest to arg1
. If you are familiar with regex
, this is equivalent
In [96]: re.match('(A+)(A+)(A+)','AAAAAAAAA').groups()
Out[96]: ('AAAAAAA', 'A', 'A')
(The parser can't read your mind and allocate all the 'arg2's to args2
just because the names look similar.:) )
So if you need to split lists of arguments in a specific way, then optionals
(flags) is the way to go. And between nargs
and required
you have quite a bit of control over the numbers.
Upvotes: 3
Reputation: 57
I added require=True and it works, thanks to hpaulj
parser = argparse.ArgumentParser()
parser.add_argument('path', type=str,
help="path used for the generation of the rouge files")
parser.add_argument('-s', '--systems', type=str, nargs='+', required=True,
help="path to the systems generated summary files")
parser.add_argument('-m', '--models', type=str, nargs='+', required=True,
help="path to the reference summary files")
args = parser.parse_args()
python summary2rouge.py
usage: summary2rouge.py [-h] -s SYSTEMS [SYSTEMS ...] -m MODELS [MODELS ...]
path
summary2rouge.py: error: too few arguments
Upvotes: 0
Reputation: 5546
What you want is not possible. Think about it: if you would implement your own argument parsing without argparse
, how would you determine if a positional argument is the last one of a list of arg1
arguments, or the first of the arg2
arguments?
I think the solution you've got know (optional arguments) works fine and is even preferable.
Upvotes: 1