Разделите dest между позиционными аргументами и опциями - PullRequest
3 голосов
/ 04 марта 2020

У меня есть очень простой экземпляр ArgumentParser с необязательным позиционным аргументом и параметром, который записывает константу в одно и то же место назначения:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-a', action='store_const', dest='path', const='<all>')
parser.add_argument('path', nargs='?')

# Prints None instead of '<all>'
print(parser.parse_args(['-a']).path)

Но, несмотря ни на что, парсинг командной строки ['-a'] не дает Namespace экземпляра с path, установленным на эту константу. Вместо этого используется значение по умолчанию из позиционного аргумента.

Что я делаю не так?

Мой пример использования заключается в том, что пользователь должен иметь возможность указать путь (фактически список путей) , Этот список путей по умолчанию соответствует текущему рабочему каталогу. Но вместо того, чтобы использовать это значение по умолчанию, можно передать -a, что должно привести к использованию некоторого настроенного каталога root. Полный код этой части парсера аргумента:

all_sentinel = object()

parser = argparse.ArgumentParser()
paths_group = parser.add_mutually_exclusive_group()
paths_group.add_argument('-a', action='store_const', dest='paths', const=all_sentinel)
paths_group.add_argument('paths', nargs='*', default=['.'])

1 Ответ

2 голосов
/ 04 марта 2020

Позиционер с nargs='?' имеет некоторую специальную обработку по умолчанию (здесь None).

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

Поскольку пустой список значений удовлетворяет nargs, этот позиционный объект всегда «виден». Но вместо того, чтобы назначать [] или какую-либо другую пустую строку, анализатор назначает значение по умолчанию. Таким образом, по умолчанию позиционное значение перезаписывает значение, установленное в '-a'.

nargs='*' получает такую ​​же специальную обработку.

Я подозреваю, что если у вас был другой позиционный аргумент перед '- а ', что вы не увидите этот эффект. Позиционал '? *' Будет обработан перед '-a' и не перезапишет его значение.

Необязательные параметры обрабатываются только при наличии флага. Позиционирование всегда обрабатывается независимо от nargs. «Дополнительные» позиционеры обрабатываются, но с некоторой дополнительной обработкой значений по умолчанию. Но когда они обрабатываются относительно помеченных аргументов, они могут различаться.

Это хитрое поведение, о котором я знаю просто потому, что подробно изучил код и ответил на множество вопросов здесь и на * 1024. * ошибка / проблемы.

Совместное использование dest часто работает, но это больше по умолчанию, чем дизайн. Это результат других вариантов дизайна. argparse не дает никаких обещаний в этом отношении. Так что, если это ненадежно, не используйте его.

...