Как правильно использовать подпарсеры argparse?

Я просмотрел множество примеров подпарсеров здесь и вообще, но, похоже, не могу понять эту, казалось бы, простую вещь.

У меня есть два типа var, один из которых имеет ограничения, поэтому я подумал, что subparser - это путь. например -t позволяет использовать либо A, либо B. Если пользователь передает A, то он также должен указать, является ли это a1 или a2. Если они пройдут только B, то ничего.

Могу ли я сделать это, и argparse вернет мне, какой тип A был передан или это был просто B?

Нижеприведенное, кажется, работает, но по какой-то причине ломается при передаче чего-либо после подразбора.

например из линукс терминала

>> python test01.py -t A a1 -v 61

ошибки с...

usage: test01.py a1 [-h]
test01.py a1: error: unrecognized arguments: -v

Надеюсь, это имеет смысл.

Код:

import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='types of A')

parser.add_argument("-t",
                    choices = ["A", "B"],
                    dest = "type",
                    required=True,
                    action='store',
                    help="Some help blah blah")

cam_parser = subparsers.add_parser('a1', help='Default')
cam_parser.set_defaults(which='a1')

cam_parser = subparsers.add_parser('a2', help='parse this instead of default')
cam_parser.set_defaults(which='a2')


parser.add_argument("-v",
                    nargs = '+',
                    required=True,
                    dest = "version",
                    type=int,
                    action='store',
                    help="some version help blah blah")   

argument = parser.parse_args()

print argument.type
print argument.version

person user1571144    schedule 12.06.2013    source источник


Ответы (1)


Подпарсеры вызываются на основе значения первого аргумента positional, поэтому ваш вызов будет выглядеть так:

python test01.py A a1 -v 61

«A» запускает соответствующий подпарсер, который должен быть определен для разрешения позиционного аргумента и опции -v.

Поскольку argparse в остальном не накладывает никаких ограничений на порядок, в котором могут появляться аргументы и параметры, и нет простого способа изменить то, какие аргументы/параметры могут появляться после начала синтаксического анализа (что-то, связанное с пользовательскими действиями, которые может сработать экземпляр синтаксического анализатора), вам следует подумать о замене самого -t:

import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='types of A')
parser.add_argument("-v", ...)

a_parser = subparsers.add_parser("A")
b_parser = subparsers.add_parser("B")

a_parser.add_argument("something", choices=['a1', 'a2'])

Поскольку -v определено для основного синтаксического анализатора, его необходимо указать перед аргументом, указывающим, какой подпарсер используется для остальных аргументов.

person chepner    schedule 12.06.2013
comment
Отлично! Большое спасибо. Однако я все еще получал сообщение об ошибке, когда по какой-то причине передал -v, то есть ожидал -v, и когда я передал его, я получил свои старые аргументы ошибки, не распознанные. Даже если я передал его перед позиционными аргументами. Любые идеи? Я пытался найти подобный пример, но мне не повезло. - person user1571144; 18.06.2013
comment
относится ли before the argument that specifies which subparser к коду пользователя, вводящего аргумент, или к тому и другому? - person Nickpick; 20.06.2017
comment
Похоже, что выполнение group1 = parser.add_subparsers(help='subparser group 1') и group2 = parser.add_subparsers(help='subparser group 2') дает error:cannot have multiple subparser arguments ошибку. Я надеялся использовать его для группировки подкоманд. - person Minh Tran; 12.02.2018
comment
@MinhTran В этом случае вам нужно будет использовать a_parser.add_subparsers() и b_parser.add_subparsers(). - person chepner; 12.02.2018