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формат?


5
Вас може зацікавити docopt . Я ніколи більше не дивився на аргументацію.
Пауло Скардін

14
@PauloScardine - Вбудована мова є головною перевагою для аргументації.
Йорданм

1
@PauloScardine: Затягування нестандартної бібліотеки до мого поточного проекту справді буде болем, але мені точно подобається вигляд результатів docopt. Дякую за пораду!
JS.

@JS. Ви кажете: "Затягнути нестандартну бібліотеку до мого поточного проекту справді буде біль" Дійсно? У pypi є дуже багато корисних бібліотек. У моєму контексті легко зайняти нестандартну бібліотеку. Сумно, якщо це важко у вашому контексті.
guettli

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=показують значення за замовчуванням? Оскільки мені не подобаються тексти "за замовчуванням: Немає".
ziyuang

14
Ви можете встановити defaultна SUPPRESS: default=argparse.SUPPRESS. Зауважте, що в цьому випадку жоден атрибут не буде доданий до результату простору імен, якщо цей аргумент опущено, див . defaultДокументацію .
Martijn Pieters

4
Зауважте, що вам потрібно вказати це також для кожного створеного підрозділу.
KomodoDave

1
Потім створіть нове запитання, включаючи мінімальний відтворюваний приклад, який демонструє проблему. Як я вже сказав, це працює для мене з Python 2.7.
Martijn Pieters

3
@David У мене була така ж проблема. Додайте helpаргумент у, add_argumentі це має спрацювати.
Пабло Діаз Огні

190

Додайте '%(default)s'до параметра довідки, щоб керувати тим, що відображається.

parser.add_argument("--type", default="toto", choices=["toto","titi"],
                              help = "type (default: %(default)s)")

9
Мені подобається цей варіант, тому що я вже використовував format_class = argparse.RawTestHelpFormatter і не відчував, як блукати з OOP.
mqsoh

23
Не забудьте включити змінну 'type' у рядок форматування-- наприклад, '% (за замовчуванням) s' для рядка або '% (за замовчуванням) d' для цифри.
strongMA

1
Мені це рішення подобається набагато краще, воно набагато простіше, і мені не потрібно явно обробляти аргументи без значень за замовчуванням.
void.pointer

@mqsoh множинне спадкування на насправді просто працював, але , до жаль , не є публічним API: stackoverflow.com/a/52025430/895245
Чіро Сантіллі郝海东冠状病六四事件法轮功

1
Мені це подобається, тому що зміна класу форматування додає купу "(за замовчуванням: Немає)" скрізь, що забиває допомогу.
6005

11

Клас обгортки

Це найнадійніший і сухий підхід, який я до цього часу знайшов, як показувати за замовчуванням, так і використовувати інший формат, наприклад 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, як це зробити.argparsedocstring говорить:

Усі інші класи в цьому модулі вважаються деталями реалізації. (Також зауважте, що HelpFormatter та RawDescriptionHelpFormatter публічними вважаються лише імена об'єктів - API об’єктів форматора все ще вважається деталі реалізації.)

Дивіться також: Налаштування довідкового аргументаційного аргументу

Тестовано на Python 3.6.5.


1
Чудово! Нарешті надруковано як відформатовані аргументи docstring, так і аргументи за замовчуванням. Спасибі
Сильвейн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.