python - How can I create an argparse mutually exclusive group with multiple positional parameters? -
i'm trying parse command-line arguments such 3 possibilities below possible:
script script file1 file2 file3 … script -p pattern thus, list of files optional. if -p pattern option specified, nothing else can on command line. said in "usage" format, this:
script [-p pattern | file [file …]] i thought way python's argparse module this:
parser = argparse.argumentparser(prog=base) group = parser.add_mutually_exclusive_group() group.add_argument('-p', '--pattern', help="operate on files match glob pattern") group.add_argument('files', nargs="*", help="files operate on") args = parser.parse_args() but python complains positional argument needs optional:
traceback (most recent call last): file "script", line 92, in <module> group.add_argument('files', nargs="*", help="files operate on") … valueerror: mutually exclusive arguments must optional but argparse documentation says "*" argument nargs meant optional.
i haven't been able find other value nargs trick either. closest i've come using nargs="?", grabs 1 file, not optional list of number.
is possible compose kind of argument syntax using argparse?
short answer
add default * positional
long
the code raising error is,
if action.required: msg = _('mutually exclusive arguments must optional') raise valueerror(msg) if add * parser, see required attribute set:
in [396]: a=p.add_argument('bar',nargs='*') in [397]: out[397]: _storeaction(option_strings=[], dest='bar', nargs='*', const=none, default=none, type=none, choices=none, help=none, metavar=none) in [398]: a.required out[398]: true while ? false. i'll have dig bit further in code see why difference. bug or overlooked 'feature', or there might reason. tricky thing 'optional' positionals no-answer answer, is, empty list of values valid.
in [399]: args=p.parse_args([]) in [400]: args out[400]: namespace(bar=[], ....) so mutually_exclusive has have way distinguish between default [] , real [].
for i'd suggest using --files, flagged argument rather positional 1 if expect argparse perform mutually exclusive testing.
the code sets required attribute of positional is:
# mark positional arguments required if @ least 1 # required if kwargs.get('nargs') not in [optional, zero_or_more]: kwargs['required'] = true if kwargs.get('nargs') == zero_or_more , 'default' not in kwargs: kwargs['required'] = true so solution specify default *
in [401]: p=argparse.argumentparser() in [402]: g=p.add_mutually_exclusive_group() in [403]: g.add_argument('--foo') out[403]: _storeaction(option_strings=['--foo'], dest='foo', nargs=none, const=none, default=none, type=none, choices=none, help=none, metavar=none) in [404]: g.add_argument('files',nargs='*',default=none) out[404]: _storeaction(option_strings=[], dest='files', nargs='*', const=none, default=none, type=none, choices=none, help=none, metavar=none) in [405]: p.parse_args([]) out[405]: namespace(files=[], foo=none) the default []. parser able distinguish between default provide , 1 uses if none given.
oops - default=none wrong. passes add_argument , required test, produces mutually_exclusive error. details lie in how code distinguishes between user defined defaults , automatic ones. use none.
i don't see in documentation this. i'll have check bug/issues see topic has been discussed. it's come on before well.
Comments
Post a Comment