Для анализа параметров логической командной строки с использованием встроенного в Python пакета argparse
мне известен этот вопрос и несколько ответов: Анализ логических значений с помощью argparse .
Несколькоиз ответов (правильно, IMO) указывают, что наиболее распространенная и простая идиома для логических опций (с точки зрения вызывающей стороны) - это принятие опций --foo
и --no-foo
, что устанавливает некоторое значение в программе на True
или False
, соответственно.
Однако все ответы, которые я могу найти, на самом деле не выполняют задачу правильно, как мне кажется.Как правило, они не соответствуют одному из следующих пунктов:
- Можно установить подходящее значение по умолчанию (
True
, False
или None
). - Текст справкиприведенный для
program.py --help
является правильным и полезным, включая показ значения по умолчанию. - Любой из (мне все равно, какие из них, но иногда желательны):
- Аргумент
--foo
может быть переопределено более поздним аргументом --no-foo
и наоборот; --foo
и --no-foo
являются несовместимыми и взаимоисключающими.
Что мне интересно, так это то, возможно ли вообще это сделать, используя argparse
.
Вот самое близкое, что я пришел, основываясь на ответах @mgilson и @fnkr:
def add_bool_arg(parser, name, help_true, help_false, default=None, exclusive=True):
if exclusive:
group = parser.add_mutually_exclusive_group(required=False)
else:
group = parser
group.add_argument('--' + name, dest=name, action='store_true', help=help_true)
group.add_argument('--no-' + name, dest=name, action='store_false', help=help_false)
parser.set_defaults(**{name: default})
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
add_bool_arg(parser, 'foo', "Do foo", "Don't foo", exclusive=True)
add_bool_arg(parser, 'bar', "Do bar", "Don't bar", default=True, exclusive=False)
Это делает большинство вещей хорошо, но текст справки вводит в заблуждение:
usage: argtest.py [-h] [--foo | --no-foo] [--bar] [--no-bar]
optional arguments:
-h, --help show this help message and exit
--foo Do foo (default: None)
--no-foo Don't foo (default: None)
--bar Do bar (default: True)
--no-bar Don't bar (default: True)
Лучшим текстом справки будет что-то вроде этого:
usage: argtest.py [-h] [--foo | --no-foo] [--bar] [--no-bar]
optional arguments:
-h, --help show this help message and exit
--foo --no-foo Whether to foo (default: None)
--bar --no-bar Whether to bar (default: True)
Но я не вижуспособ сделать это, так как "- *" и "--no- *" всегда должны быть объявлены как отдельные аргументы (верно?).
В дополнение к suggeВ ответах на вопрос SO, упомянутый выше, я также попытался создать пользовательское действие, используя методы, показанные в этом другом вопросе SO: Python argparse настраиваемые действия с дополнительными аргументами, переданными .Они сразу перестают говорить, либо "error: argument --foo: expected one argument"
, либо (если я установил nargs=0
) "ValueError: nargs for store actions must be > 0"
.Из-за поиска в источнике argparse
это выглядит так, потому что действия, отличные от предопределенных store_const, store_true, append и т. Д., Должны использовать класс _StoreAction
, который требует аргумент.
Есть ли другой способ сделать это?Если у кого-то есть комбинация идей, о которых я еще не подумал, пожалуйста, дайте мне знать!
(Кстати, я создаю этот новый вопрос, а не пытаюсь добавить его к первому вопросу выше, потому чтоПервоначальный вопрос, приведенный выше, на самом деле требовал метода для обработки аргументов --foo TRUE
и --foo FALSE
, который отличается и ИМО встречается реже.