Argparse: Maneira de incluir valores padrão em '--help'?

307

Suponha que eu tenha o seguinte trecho de argumento:

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

Atualmente, --helpretorna:

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.

Eu preferiria algo como:

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

Espreitar o código do formatador de ajuda revelou opções limitadas. Existe uma maneira inteligente argparsede imprimir o valor padrão de --scan-timemaneira semelhante ou devo apenas subclassificar o helpformatador?

JS.
fonte
5
Você pode estar interessado em docopt . Nunca mais olhei para o argparse.
Paulo Scardine 28/08/12
14
@PauloScardine - Ser incorporado ao idioma é um grande benefício para o argparse.
Jordanm
1
@PauloScardine: Puxar uma biblioteca não-padrão para o meu projeto atual será realmente uma dor, mas eu certamente gosto da aparência da saída do docopt. Obrigado pela dica!
JS.
@JS. você diz "Colocar uma biblioteca não-padrão no meu projeto atual será realmente uma dor" Sério? Existem muitas bibliotecas muito úteis no pypi. No meu contexto, é fácil extrair uma biblioteca não padrão. É triste, se é difícil no seu contexto.
guettli
3
@ guettli: Esse projeto foi para um projeto comercial incorporado. Você está certo, a instalação foi fácil. Obter a aprovação do departamento jurídico da empresa foi um pesadelo.
JS.

Respostas:

447

Use o argparse.ArgumentDefaultsHelpFormatterformatador :

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

Para citar a documentação:

A outra classe de formatador disponível ArgumentDefaultsHelpFormatter,, adicionará informações sobre o valor padrão de cada um dos argumentos.

Observe que isso se aplica apenas a argumentos que possuem texto de ajuda definido ; sem helpvalor para um argumento, não há nenhuma mensagem de ajuda para adicionar informações sobre o valor padrão para .

A saída exata para a sua opção de tempo de varredura se torna:

  --scan-time [SCAN_TIME]
                        Wait SCAN-TIME seconds between status checks.
                        (default: 5)
Martijn Pieters
fonte
12
Posso controlar que apenas os argumentos com um explícito default=mostram o valor padrão? Como não gosto dos textos 'default: None'.
precisa saber é o seguinte
14
Você pode definir o defaultque SUPPRESS: default=argparse.SUPPRESS. Observe que, nesse caso, nenhum atributo será adicionado ao resultado do espaço para nome se esse argumento for omitido, consulte a defaultdocumentação .
Martijn Pieters
4
Observe que você precisa especificar isso para cada sub-analisador criado também.
KomodoDave
1
Em seguida, crie uma nova pergunta, incluindo um exemplo reproduzível mínimo que demonstre o problema. Como eu disse, ele funciona para mim com o Python 2.7.
Martijn Pieters
3
@ David Eu estava tendo o mesmo problema. Adicione o helpargumento add_argumente isso deve funcionar.
Pablo Díaz Ogni
190

Adicione '%(default)s'ao parâmetro de ajuda para controlar o que é exibido.

parser.add_argument("--type", default="toto", choices=["toto","titi"],
                              help = "type (default: %(default)s)")
polux.moon
fonte
9
Eu gosto dessa opção porque eu já havia usado o format_class = argparse.RawTestHelpFormatter e não estava com vontade de peidar com o OOP.
Mqsoh
23
Não se esqueça de incluir a variável 'type' na sua string de formatação - por exemplo, '% (padrão) s' para uma string ou '% (padrão) d' para um dígito.
strongMA
1
Gosto muito desta solução, é muito mais simples e não preciso lidar explicitamente com argumentos sem valores padrão.
precisa saber é o seguinte
@mqsoh herança múltipla realmente só funcionou, mas, infelizmente, não é API pública: stackoverflow.com/a/52025430/895245
Ciro Santilli郝海东冠状病六四事件法轮功
1
Eu gosto disso porque alterar a classe do formatador adiciona um monte de "(padrão: Nenhum)" em todos os lugares que estão sobrecarregando a ajuda.
6005
11

Classe Wrapper

Essa é a abordagem mais confiável e DRY que eu encontrei até agora para mostrar padrões e usar outro formatador, como argparse.RawTextHelpFormatterao mesmo tempo:

#!/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())

Resultado:

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+ RawTextHelpFormatterherança múltipla

A herança múltipla simplesmente funciona, mas não parece ser uma API pública:

#!/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()

Resultado:

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)

Ele simplesmente funciona funciona porque, como podemos ver trivialmente das fontes https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648, que:

  • RawTextHelpFormatter implementa _split_lines
  • ArgumentDefaultsHelpFormatter implementa _get_help_string

para que possamos adivinhar que eles funcionarão juntos muito bem.

No entanto, isso não parece ser uma API pública, nem os métodos formatter_class, então não acho que exista uma maneira pública de fazer isso atualmente. argparsedocstring diz:

Todas as outras classes neste módulo são consideradas detalhes de implementação. (Observe também que HelpFormatter e RawDescriptionHelpFormatter são considerados públicos apenas como nomes de objetos - a API dos objetos do formatador ainda é considerada um detalhe de implementação.)

Consulte também: Personalizar a mensagem de ajuda do argparse

Testado em Python 3.6.5.

Ciro Santilli adicionou uma nova foto
fonte
1
Ótimo ! Finalmente, impressos os argumentos da documentação formatada e padrão. Obrigado
Sylvain