Argparse: ¿Manera de incluir valores predeterminados en '--help'?
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, --help
regresa:
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 argparse
el valor predeterminado de --scan-time
de manera similar, o debería simplemente subclasificar el help
formateador?
Utilice el argparse.ArgumentDefaultsHelpFormatter
formateador :
parser = argparse.ArgumentParser(
# ... other options ...
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
Para citar la documentación :
La otra clase de formateador disponible,
ArgumentDefaultsHelpFormatter
agregará 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 help
valor 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)
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 enformat
o f-string) - No olvide agregar el "carácter especificador" para la representación del tipo al final (es decir,
s
para cadenas,d
números enteros,f
flotantes, 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.
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.RawTextHelpFormatter
al 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
+ RawTextHelpFormatter
herencia 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:
RawTextHelpFormatter
implementos_split_lines
ArgumentDefaultsHelpFormatter
implementos_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. argparse
cadena 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 default
valores 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.SUPPRESS
es necesario agregarlo manualmente para cada uno de estos argumentos.El
'%(default)s'
método requiere agregarlo manualmente a todas lashelp
cadenas 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 ArgumentDefaultsHelpFormatter
para ignorar los valores predeterminados de None
s 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 default
valores establecidos explícitamente en la salida de ayuda.
Nota: si el valor predeterminado de un argumento se estableció explícitamente como None
o False
, no se mostrará en la ayuda de esta clase; agregue %(default)s
una cadena help
para ese argumento si lo desea en la salida de ayuda.