Argparse: ¿Manera de incluir valores predeterminados en '--help'?

Resuelto JS. asked hace 12 años • 4 respuestas

Supongamos que tengo el siguiente fragmento de argparse:

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

Actualmente, --helpregresa:

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.

Preferiría algo como:

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

Echar un vistazo al código de ayuda del formateador reveló opciones limitadas. ¿Existe una manera inteligente de imprimir argparseel valor predeterminado de --scan-timede manera similar, o debería simplemente subclasificar el helpformateador?

JS. avatar Aug 28 '12 07:08 JS.
Aceptado

Utilice el argparse.ArgumentDefaultsHelpFormatterformateador :

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

Para citar la documentación :

La otra clase de formateador disponible, ArgumentDefaultsHelpFormatteragregará información sobre el valor predeterminado de cada uno de los argumentos.

Tenga en cuenta que esto sólo se aplica a argumentos que tienen texto de ayuda definido ; sin helpvalor para un argumento, no hay ningún mensaje de ayuda para agregar información sobre el valor predeterminado .

El resultado exacto para su opción de tiempo de escaneo se convierte en:

  --scan-time [SCAN_TIME]
                        Wait SCAN-TIME seconds between status checks.
                        (default: 5)
Martijn Pieters avatar Aug 28 '2012 00:08 Martijn Pieters

Agregue '%(default)s'al parámetro de ayuda para controlar lo que se muestra.

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

Notas :

  • Es %+ predeterminado entre paréntesis + caracteres de formato (no debe confundirse con las llaves {default}que encontramos en formato f-string)
  • No olvide agregar el "carácter especificador" para la representación del tipo al final (es decir, spara cadenas, dnúmeros enteros, fflotantes, etc.)
  • También puede agregar los especificadores de formato "printf" habituales (como el número de dígitos para puntos flotantes, ceros a la izquierda, etc.)

Puede consultar la documentación de printf para obtener más detalles.

polux.moon avatar Aug 29 '2013 10:08 polux.moon

clase contenedora

Este es el enfoque más confiable y SECO que he encontrado hasta ahora para mostrar los valores predeterminados y usar otro formateador como argparse.RawTextHelpFormatteral mismo tiempo:

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

Producción:

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+ RawTextHelpFormatterherencia múltiple

La herencia múltiple simplemente funciona, pero no parece ser una 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()

Producción:

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)

Simplemente funciona porque, como podemos ver trivialmente en las fuentes https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648 , eso:

  • RawTextHelpFormatterimplementos_split_lines
  • ArgumentDefaultsHelpFormatterimplementos_get_help_string

entonces podemos suponer que funcionarán bien juntos.

Sin embargo, esto no parece ser una API pública, y tampoco lo son los métodos de formatter_class, por lo que no creo que exista una forma de API pública para hacerlo actualmente. argparsecadena de documentos dice:

Todas las demás clases de este módulo se consideran detalles de implementación. (Tenga en cuenta también que HelpFormatter y RawDescriptionHelpFormatter solo se consideran públicos como nombres de objetos; la API de los objetos formateadores todavía se considera un detalle de implementación).

Ver también: Personalizar el mensaje de ayuda de argparse

Probado en Python 3.6.5.

A menudo resulta útil poder incluir automáticamente los defaultvalores en la salida de ayuda, pero solo aquellos que se especificaron explícitamente (con default=..). Los métodos ya mencionados tienen algunas deficiencias a este respecto:

  • El ArgumentDefaultsHelpFormatter método imprime (default: None)para cada argumento cuyo valor predeterminado no se especificó explícitamente y (default: False)para las 'banderas' ( action='store_true'). Esto satura la salida de ayuda. Para evitarlo, default=argparse.SUPPRESSes necesario agregarlo manualmente para cada uno de estos argumentos.

  • El '%(default)s' método requiere agregarlo manualmente a todas las helpcadenas de argumentos que queremos imprimir en la ayuda.

Ambos métodos terminan necesitando intervención manual para imprimir sólo los valores predeterminados "correctos". Una forma de hacer esto automáticamente es aumentar the ArgumentDefaultsHelpFormatterpara ignorar los valores predeterminados de Nones y s:False

class ExplicitDefaultsHelpFormatter(argparse.ArgumentDefaultsHelpFormatter):
    def _get_help_string(self, action):
        if action.default is None or action.default is False:
            return action.help
        return super()._get_help_string(action)

Úselo en lugar de ArgumentDefaultsHelpFormatter:

parser = argparse.ArgumentParser(
        formatter_class=ExplicitDefaultsHelpFormatter
                )

Esto imprimirá solo los defaultvalores establecidos explícitamente en la salida de ayuda.

Nota: si el valor predeterminado de un argumento se estableció explícitamente como Noneo False, no se mostrará en la ayuda de esta clase; agregue %(default)suna cadena helppara ese argumento si lo desea en la salida de ayuda.

exquo avatar Apr 22 '2021 06:04 exquo