параметр argparse arg с использованием nargs='?' перед позиционным аргументом в субпарсере

import argparse

parser = argparse.ArgumentParser()
parser.add_argument(
    '--optional',
    default=None,
    const='some-const',
    nargs='?',
    help='optional')

subparsers = parser.add_subparsers()

subparser = subparsers.add_parser('subparser')

subparser.add_argument(
    'positional',
    help='positional')

args = parser.parse_args()

print args

./test.py --optional opt subparser positional
Namespace(optional='opt', positional='positional')  <-- works as expected

./test.py --optional subparser positional
usage: test.py [-h] [--optional [OPTIONAL]] {subparser} ...
test.py: error: invalid choice: 'positional' (choose from 'subparser')  <-- throws an error
 Namespace(optional='some-const', positional='positional')  <-- would expect to see this

Выше приведен мой простейший тестовый код для демонстрации этой проблемы. Я хотел бы иметь необязательный аргумент, используя nargs='?' и const перед моим позиционным аргументом в подпарсере. Я читал, что могу передать исходный синтаксический анализатор в качестве родителя дочернему подпарсеру, но это не решает проблему. Я попытался добавить add_help=False и конфликт_обработчик='resolve' в начальное объявление синтаксического анализатора, когда пытался это сделать. Может ли кто-нибудь указать мне правильное направление в этом?

Спасибо, Скотт


person Scott Idler    schedule 18.12.2012    source источник
comment
Почему определение --optional как родителя подпарсера не решает проблему? Вы все равно должны позвонить subparser, так какая разница, если вы назовете это --optional subparser POS или subparser POS --optional? Я не решаюсь назвать это ошибкой, но, читая документацию и играя, она бросает вызов моим ожиданиям :) Тем не менее, если вы можете ее обойти...   -  person Zach Young    schedule 02.01.2013
comment
subparser POS --optional тоже не работает с этим кодом.   -  person jgritty    schedule 02.01.2013


Ответы (2)


При синтаксическом анализе ./test.py --optional foo bar argparse видит необязательную строку (начинается с --), за которой следуют две строки аргументов (без --)

Итак, он начинается с обработки --optional. Это nargs является «жадным?», поэтому он потребляет аргумент foo, создавая:

Namespace('optional'='foo')

Это оставляет bar для использования в качестве аргумента подкоманды.

Он не проверяет, является ли foo допустимым аргументом подкоманды.

То же самое относится и к ./test.py --optional subparser positional.

person hpaulj    schedule 15.08.2013

Это вызывает ошибку:

.test.py --optional

Поскольку subparser не является обязательным:

usage: subparser.py [-h] [--optional [OPTIONAL]] {subparser} ...
test.py: error: too few arguments

subparser съедается и используется как OPTIONAL во втором примере. Я не понимаю, почему, кроме того, что argparse заранее не выясняет, что подпарсер является подпарсером.

Это самое близкое, что я мог сделать к тому, что вы описываете:

import argparse

parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument(
    '--optional',
    nargs='?',
    default=None,
    const='some-const',
    help='optional')

sub_parser = argparse.ArgumentParser(parents=[parent_parser])
sub_parser.add_argument('--subparser', required=True)

args = sub_parser.parse_args()

print args

Я думаю, вы обнаружили ошибку.

person jgritty    schedule 02.01.2013