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')