Python argparse mutual exclusive group
мне нужно:
pro [-a xxx | [-b yyy -c zzz]]
Я пробовал это, но не работает. Может кто-нибудь мне помочь?
group= parser.add_argument_group('Model 2')
group_ex = group.add_mutually_exclusive_group()
group_ex.add_argument("-a", type=str, action = "store", default = "", help="test")
group_ex_2 = group_ex.add_argument_group("option 2")
group_ex_2.add_argument("-b", type=str, action = "store", default = "", help="test")
group_ex_2.add_argument("-c", type=str, action = "store", default = "", help="test")
спасибо!
3 ответа:
add_mutually_exclusive_groupне делает всю группу взаимоисключающей. Это делает опции внутри группы взаимоисключающими.то, что вы ищете-это команды. Вместо prog [- a xxxx | [- b yyy-c zzz]] у вас будет:
prog command 1 -a: ... command 2 -b: ... -c: ...для вызова с первым набором аргументов:
prog command_1 -a xxxxдля вызова со вторым набором аргументов:
prog command_2 -b yyyy -c zzzzвы также можете установить аргументы субкоманды как позиционный.
prog command_1 xxxxвроде как git или svn:
git commit -am git merge developПример Работающего
# create the top-level parser parser = argparse.ArgumentParser(prog='PROG') parser.add_argument('--foo', action='store_true', help='help for foo arg.') subparsers = parser.add_subparsers(help='help for subcommand') # create the parser for the "command_1" command parser_a = subparsers.add_parser('command_1', help='command_1 help') parser_a.add_argument('a', type=str, help='help for bar, positional') # create the parser for the "command_2" command parser_b = subparsers.add_parser('command_2', help='help for command_2') parser_b.add_argument('-b', type=str, help='help for b') parser_b.add_argument('-c', type=str, action='store', default='', help='test')
пока Джонатан отлично подходит для сложных вариантов, есть очень простое решение, которое будет работать для простых случаев, например, 1 вариант исключает 2 других варианта, как в
command [- a xxx | [ -b yyy | -c zzz ]]или даже как в исходном вопросе:
pro [-a xxx | [-b yyy -c zzz]]вот как бы я это сделал:
parser = argparse.ArgumentParser() # group 1 parser.add_argument("-q", "--query", help="query", required=False) parser.add_argument("-f", "--fields", help="field names", required=False) # group 2 parser.add_argument("-a", "--aggregation", help="aggregation", required=False)я использую здесь параметры, заданные оболочке командной строки для запроса mongodb. Элемент
collectionэкземпляр может либо вызвать методaggregateили методfindС необязательными аргументамиqueryиfields, следовательно, вы понимаете, почему первые два аргумента совместимы, а последний-нет.так что теперь я бегу
parser.parse_args()и проверьте его содержание:args = parser().parse_args() print args.aggregation if args.aggregation and (args.query or args.fields): print "-a and -q|-f are mutually exclusive ..." sys.exit(2)конечно, этот маленький хак работает только для простых случаев, и это станет кошмаром, чтобы проверить все возможные варианты, если у вас есть много взаимоисключающих вариантов и групп. В этом случае вы должны разбить свои параметры на группы команд как и предлагал Джонатан.
есть патч python (в разработке), который позволит вам сделать это.
http://bugs.python.org/issue10984идея состоит в том, чтобы разрешить перекрывающиеся взаимоисключающие группы. Так что
usageможет выглядеть так:pro [-a xxx | -b yyy] [-a xxx | -c zzz]изменение кода argparse, так что вы можете создать две группы, как это было легко. Изменение
usageформатирование кода требуется написание пользовательскогоHelpFormatter.на
argparse, инициативных групп не влияет на разбор. Они просто форматирование. Вhelp, взаимоисключающие группы влияют только наusageлинии. При разборе, тоparserиспользует взаимоисключающие группы для построения словаря потенциальных конфликтов (aне может произойти сbилиc,bне может произойти сaи т. д.), а затем выдает ошибку, если возникает конфликт.без этого патча argparse, я думаю, что ваш лучший выбор-проверить пространство имен произведено
parse_argsсами (например, если обаaиbимеют значения по умолчанию), и поднять свою собственную ошибку. Вы даже можете использовать собственный механизм ошибок парсера.parser.error('custom error message')