argparse: Как отделить неизвестные (и необязательные) аргументы, когда присутствуют подпарсеры (подпарсеры также необязательны) - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть следующий код

parser = argparse.ArgumentParser(allow_abbrev=False, add_help=False)
parser.add_argument('--conf', nargs=1)
parser.add_argument('-h', '--help', nargs='?', const='generic')
parser.add_argument('-v', '--version', action="store_true")

subparsers = parser.add_subparsers()
subparsers.required = False
parser_start = subparsers.add_parser('start')
group1 = parser_start.add_mutually_exclusive_group()
group1.add_argument('--quiet', action="store_true")
group1.add_argument('-V', '--verbose', nargs="*")

# parser_console = subparsers.add_parser('console')

print(argv)
parsed_args = parser.parse_known_args(argv)

Теперь, когда я передаю argv как argv = ['abc', 'def'] или argv = ['abc']

, я получаю

['abc', 'def']
usage: lbrynet [--conf CONF] [-h [HELP]] [-v] {start} ...
lbrynet: error: invalid choice: 'abc' (choose from 'start')

Я ожидал получить ['abc', 'def'] в кортеже для неизвестных аргументов.Я проверил много ответов на стеке (например, и 1 , и 2 , и 3 , и 4 ) и ошибку.отчеты (например, br 1 ) и лот , но я не могу найти способ сделать это.Это нерешенная ошибка?Я ошибаюсь, ожидая, что это может быть сделано.Если это не может быть сделано, есть ли какие-либо обходные пути для этого?

Также, чтобы уточнить, ['abc', 'def'] полученный из кортежа должен быть передан какой-то другой функции для обработки.

Рад предоставить любые дальнейшие разъяснения и / или устранить любые неясности.

1 Ответ

0 голосов
/ 04 декабря 2018

Как я уже писал в комментарии, подпарасеры - это позиционный аргумент.

Для иллюстрации с простым позиционным:

In [307]: parser = argparse.ArgumentParser()
In [308]: a1 = parser.add_argument('foo')

In [309]: parser.parse_known_args(['one','two'])
Out[309]: (Namespace(foo='one'), ['two'])

'one' назначается первому позиционному.Теперь задайте foo варианты:

In [310]: a1.choices = ['bar','test']
In [311]: parser.parse_known_args(['one','two'])
usage: ipython3 [-h] {bar,test}
ipython3: error: argument foo: invalid choice: 'one' (choose from 'bar', 'test')

Он все еще пытается выделить первую строку для foo.Поскольку он не соответствует choices, возникает ошибка.

In [312]: parser.parse_known_args(['bar','one','two'])
Out[312]: (Namespace(foo='bar'), ['one', 'two'])

Строки назначаются позиционерам на основе позиции, а не значения.Любая проверка значений, например, типа или выбора, выполняется после присвоения.

Измените choices на type тест:

In [313]: a1.choices = None
In [314]: a1.type = int
In [315]: parser.parse_known_args(['bar','one','two'])
usage: ipython3 [-h] foo
ipython3: error: argument foo: invalid int value: 'bar'

In [316]: parser.parse_known_args(['12','one','two'])
Out[316]: (Namespace(foo=12), ['one', 'two'])
...