Ответ 1
короткий ответ
Добавьте default
в *
positional
долго
Код, который вызывает ошибку,
if action.required:
msg = _('mutually exclusive arguments must be optional')
raise ValueError(msg)
Если я добавлю * в синтаксический анализатор, я вижу, что атрибут required
установлен:
In [396]: a=p.add_argument('bar',nargs='*')
In [397]: a
Out[397]: _StoreAction(option_strings=[], dest='bar', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [398]: a.required
Out[398]: True
тогда как для a ?
это будет False. Я буду копать немного дальше в коде, чтобы понять, почему разница. Это может быть ошибка или пропущенная "функция", или может быть веская причина. Трудная вещь с "необязательными" позициями заключается в том, что ответ "нет" - это ответ, т.е. Допустимый пустой список значений.
In [399]: args=p.parse_args([])
In [400]: args
Out[400]: Namespace(bar=[], ....)
Таким образом, у mutally_exclusive должен быть какой-то способ отличить по умолчанию []
и real []
.
Теперь я бы предложил использовать --files
, помеченный аргумент, а не позиционный, если вы ожидаете, что argparse
выполнит взаимоисключающее тестирование.
Код, устанавливающий атрибут required
позиционного элемента:
# mark positional arguments as required if at least one is
# always required
if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
kwargs['required'] = True
if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
kwargs['required'] = True
Таким образом, решение должно указывать значение по умолчанию для *
In [401]: p=argparse.ArgumentParser()
In [402]: g=p.add_mutually_exclusive_group()
In [403]: g.add_argument('--foo')
Out[403]: _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [404]: g.add_argument('files',nargs='*',default=None)
Out[404]: _StoreAction(option_strings=[], dest='files', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [405]: p.parse_args([])
Out[405]: Namespace(files=[], foo=None)
По умолчанию может быть даже []
. Синтаксический анализатор может различать предоставленный вами по умолчанию и тот, который он использует, если он не указан.
oops - default=None
был неправильным. Он передает тест add_argument
и required
, но создает взаимно-исключающую ошибку. Подробности заключаются в том, как код различает установленные пользователем значения по умолчанию и автоматические. Поэтому используйте ничего, кроме None
.
Я ничего не вижу в документации по этому поводу. Я должен проверить ошибку/проблемы, чтобы увидеть, что тема обсуждалась. Вероятно, он тоже появился на SO.