How to include one positional argument into argparse mutually exclusive group?

亡梦爱人 提交于 2019-12-13 12:07:30

问题


I know that does not make sense multiple positional arguments into a mutually exclusive group because you can't say who is who. But I need to include ONE positional argument into that.

What I need:

$ myprogram -h
usage: myprogram [-h] [--delete value | --update value | value]

Where positional value is the default action (kind of "--include"). (myprogram without arguments must be valid too).

My first attempt (this doesn't works):

parser = ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('--delete', metavar='value')
group.add_argument('--update', metavar='value')
group.add_argument('value')

Is that possible?


Second attempt:

parser = ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('--delete', action='store_true')
group.add_argument('--update', action='store_true')
group.add_argument('--insert', action='store_true', default=True)
group.add_argument('value')

回答1:


I'd do this a little bit differently:

parser = ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.set_defaults(mode='insert')
group.add_argument('--delete', action='store_const', dest='mode', const='delete')
group.add_argument('--update', action='store_const', dest='mode', const='update')
group.add_argument('--insert', action='store_const', dest='mode', const='insert')
parser.add_argument('value', nargs='?')
args = parser.parse_args()

If you additionally want to make program --delete (with no value option) fail, add

if args.mode != 'insert' and args.value:
    parser.error("can't {} without a value argument".format(args.mode))

Note that this will mean that program --insert (with no value) still works. You could avoid this with a little more effort by having the default mode be None, doing the check above with args.mode is not None, and then doing if args.mode is None: args.mode = 'insert' or similar.




回答2:


Your syntax is more clearly described as:

myprogram {--insert|--update|--delete} value

where --insert defaults to True and value is required.

argparse can make you feel like your desired syntax must fit its model when something like

if args.insert and (args.update or args.delete):
    parser.print_help()

is much more obvious.

Added in response to comment:

Here is pseudo-code (meaning I didn't test it) which shows how I would implement this:

parser.add_argument('--insert', action='store_true')
parser.add_argument('--update', action='store_true')
parser.add_argument('--delete', action='store_true')
parser.add_argument('value')
args = parser.parse_args(sys.argv)
if ((args.insert and args.delete) or
    (args.insert and args.update) or
    (args.update and args.delete)):
    # can't pick more than one, complain and quit 
elif not (args.update or args.delete):
    # they specified no action so assume insert
    args.insert = True

# now one and only one of insert/update/delete is
# True and args.value contains the argument

I hope that makes things more clear.




回答3:


Make the positional argument optional (with '?')

parser = ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('--delete', metavar='value')
group.add_argument('--update', metavar='value')
group.add_argument('value', nargs='?')

usage is then:

usage: ipython [-h] [--delete value | --update value | value]


来源:https://stackoverflow.com/questions/15857953/how-to-include-one-positional-argument-into-argparse-mutually-exclusive-group

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!