Argparse: способ включить значения по умолчанию в '--help'?

307

Предположим, у меня есть следующий фрагмент argparse:

diags.cmdln_parser.add_argument( '--scan-time',
                     action  = 'store',
                     nargs   = '?',
                     type    = int,
                     default = 5,
                     help    = "Wait SCAN-TIME seconds between status checks.")

В настоящее время --helpвозвращается:

usage: connection_check.py [-h]
                             [--version] [--scan-time [SCAN_TIME]]

          Test the reliability/uptime of a connection.



optional arguments:
-h, --help            show this help message and exit
--version             show program's version number and exit
--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.

Я бы предпочел что-то вроде:

--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.
                    (Default = 5)

Подглядывание за помощью в коде форматера показало ограниченные возможности. Есть ли умный способ получить argparseзначение по умолчанию для --scan-timeаналогичным образом, или я должен просто подклассифицировать helpформаттер?

JS.
источник
5
Вы можете быть заинтересованы в Docopt . Я никогда не смотрел на argparse снова.
Пауло Скардин
14
@PauloScardine - Быть встроенным в язык - главное преимущество argparse.
Иордания
1
@PauloScardine: Внедрение нестандартной библиотеки в мой текущий проект действительно будет болезненным, но мне наверняка нравится, как выглядит вывод docopt. Спасибо за чаевые!
JS.
@JS. Вы говорите: «Внедрение нестандартной библиотеки в мой текущий проект действительно будет проблемой». Правда? В pypi много очень полезных библиотек. В моем контексте легко вытащить нестандартную библиотеку. Грустно, если это сложно в вашем контексте.
Геттли
3
@guettli: Этот проект был для коммерческого встраиваемого проекта. Вы правы, установка была легкой. Получение одобрения от корпоративного права было кошмаром.
JS.

Ответы:

447

Используйте argparse.ArgumentDefaultsHelpFormatterформаттер :

parser = argparse.ArgumentParser(
    # ... other options ...
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)

Цитировать документацию:

Другой доступный класс форматера, ArgumentDefaultsHelpFormatterдобавит информацию о значении по умолчанию каждого из аргументов.

Обратите внимание, что это относится только к аргументам, для которых определен текст справки ; без helpзначения аргумента отсутствует справочное сообщение, в которое можно добавить информацию о значении по умолчанию .

Точный вывод для вашего параметра времени сканирования становится следующим:

  --scan-time [SCAN_TIME]
                        Wait SCAN-TIME seconds between status checks.
                        (default: 5)
Мартейн Питерс
источник
12
Могу ли я контролировать, что только аргументы с явным значением default=показывают значение по умолчанию? Поскольку мне не нравятся тексты «default: None».
Цзыюан
14
Вы можете установить defaultна SUPPRESS: default=argparse.SUPPRESS. Обратите внимание , что в этом случае не атрибут не будет добавлен к результату пространства имен , если этот аргумент был опущен, см в defaultдокументации .
Мартин Питерс
4
Обратите внимание, что вам нужно указать это также для каждого созданного подпарсера.
KomodoDave
1
Затем создайте новый вопрос, включая минимальный воспроизводимый пример, который демонстрирует проблему. Как я уже сказал, у меня работает с Python 2.7.
Мартин Питерс
3
@ Дэвид У меня была такая же проблема. Добавьте helpаргумент в add_argumentи это должно работать.
Пабло Диас Огни
190

Добавьте '%(default)s'к параметру справки, чтобы контролировать то, что отображается.

parser.add_argument("--type", default="toto", choices=["toto","titi"],
                              help = "type (default: %(default)s)")
polux.moon
источник
9
Мне нравится эта опция, потому что я уже использовал format_class = argparse.RawTestHelpFormatter и не чувствовал, что нужно дурачиться с ООП.
mqsoh
23
Не забудьте включить переменную type в строку форматирования, например, «% (по умолчанию) s» для строки или «% (по умолчанию) d» для цифры.
strongMA
1
Мне нравится это решение намного лучше, оно намного проще, и мне не нужно явно обрабатывать аргументы без значений по умолчанию.
void.pointer
Множественное наследование @mqsoh на самом деле только что сработало, но, к сожалению, оно не является публичным API: stackoverflow.com/a/52025430/895245
Сиро Сантилли
1
Мне это нравится, потому что изменение класса форматера добавляет кучу "(по умолчанию: нет)" везде, что загромождает помощь.
6005
11

Класс Wrapper

Это самый надежный и СУХОЙ подход, который я нашел до сих пор, чтобы показывать значения по умолчанию и использовать другой форматер, такой как argparse.RawTextHelpFormatter:

#!/usr/bin/env python3

import argparse

class ArgumentParserWithDefaults(argparse.ArgumentParser):
    def add_argument(self, *args, help=None, default=None, **kwargs):
        if help is not None:
            kwargs['help'] = help
        if default is not None and args[0] != '-h':
            kwargs['default'] = default
            if help is not None:
                kwargs['help'] += ' Default: {}'.format(default)
        super().add_argument(*args, **kwargs)

parser = ArgumentParserWithDefaults(
    formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.add_argument('--no-default', help='''my help
for no-default''')
parser.add_argument('--no-help', default=101)

parser.print_help()
print()
print(parser.parse_args())

Вывод:

usage: main.py [-h] [-a A] [-b B] [--no-default NO_DEFAULT]
               [--no-help NO_HELP]

optional arguments:
  -h, --help            show this help message and exit
  -a A                  my help
                        for a Default: 13
  -b B                  my help
                        for b Default: 42
  --no-default NO_DEFAULT
                        my help
                        for no-default
  --no-help NO_HELP

Namespace(a=13, b=42, no_default=None, no_help=101)

ArgumentDefaultsHelpFormatter+ RawTextHelpFormatterмножественное наследование

Множественное наследование просто работает, но оно не является публичным API:

#!/usr/bin/env python3

import argparse

class RawTextArgumentDefaultsHelpFormatter(
        argparse.ArgumentDefaultsHelpFormatter,
        argparse.RawTextHelpFormatter
    ):
        pass

parser = argparse.ArgumentParser(
    formatter_class=RawTextArgumentDefaultsHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.print_help()

Вывод:

usage: a.py [-h] [-a A] [-b B]

optional arguments:
  -h, --help  show this help message and exit
  -a A        my help
              for a (default: 13)
  -b B        my help
              for b (default: 42)

Это просто работает работает, потому что, как мы можем легко увидеть из источников https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648, что:

  • RawTextHelpFormatter инвентарь _split_lines
  • ArgumentDefaultsHelpFormatter инвентарь _get_help_string

так что мы можем догадаться, что они будут отлично работать вместе.

Тем не менее, это не похоже на публичный API, как и методы formatter_class, поэтому я не думаю, что в настоящее время существует публичный способ API сделать это. argparseДокстринг говорит:

Все остальные классы в этом модуле считаются деталями реализации. (Также обратите внимание, что HelpFormatter и RawDescriptionHelpFormatter считаются открытыми только как имена объектов - API объектов форматирования все еще считается деталью реализации.)

См. Также: Настройка сообщения справки argparse.

Протестировано на Python 3.6.5.

Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
1
Большой ! Наконец, напечатаны обе отформатированные строки документации и аргументы по умолчанию. Спасибо
Сильвен