usage metavar float example argumentparser argument python argparse

python - metavar - argparse subparser ayuda monolítica de salida



argparse python example (5)

Mi argparse tiene solo 3 marcas (store_true) en el nivel superior, todo lo demás se maneja a través de subparsers. Cuando ejecuto myprog.py --help , la salida muestra una lista de todos los subcomandos como normal, {sub1, sub2, sub3, sub4, ...} . Por lo tanto, el valor predeterminado está funcionando muy bien ...

Normalmente no recuerdo el nombre exacto del subcomando que necesito, y todas sus opciones. Así que termino haciendo 2 búsquedas de ayuda:

myprog.py --help myprog.py sub1 --help

Hago esto muy a menudo, decidí meter esto en un solo paso. Preferiría que mi ayuda de alto nivel produjera un gran resumen y luego me desplazo manualmente por la lista. Me parece que es mucho más rápido (al menos para mí).

Estaba usando un RawDescriptionHelpFormatter y estaba escribiendo manualmente la salida de ayuda larga. Pero ahora tengo muchos subcomandos, y se está convirtiendo en un dolor para manejar.

¿Hay alguna forma de obtener una salida de ayuda detallada con una sola llamada de programa?

De lo contrario, ¿cómo puedo iterar los subparsers de mi instancia de argparse y luego recuperar la salida de ayuda individualmente de cada uno (que luego pegaré)?

Aquí hay un resumen rápido de mi configuración argparse. Limpié / quité el código un poco, por lo que es posible que esto no funcione sin un poco de ayuda.

parser = argparse.ArgumentParser( prog=''myprog.py'', formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.dedent(""" You can manually type Help here """) ) parser.add_argument(''--debuglog'', action=''store_true'', help=''Verbose logging for debug purposes.'') parser.add_argument(''--ipyonexit'', action=''store_true'', help=''Drop into an embeded Ipython session instead of exiting command.'') subparser = parser.add_subparsers() ### --- Subparser B parser_b = subparser.add_parser(''pdfreport'', description="Used to output reports in PDF format.") parser_b.add_argument(''type'', type=str, choices=[''flatlist'', ''nested'', ''custom''], help="The type of PDF report to generate.") parser_b.add_argument(''--of'', type=str, default='''', help="Override the path/name of the output file.") parser_b.add_argument(''--pagesize'', type=str, choices=[''letter'', ''3x5'', ''5x7''], default=''letter'', help="Override page size in output PDF.") parser_b.set_defaults(func=cmd_pdf_report) ### ---- Subparser C parser_c = subparser.add_parser(''dbtables'', description="Used to perform direct DB import/export using XLS files.") parser_c.add_argument(''action'', type=str, choices=[''push'', ''pull'', ''append'', ''update''], help="The action to perform on the Database Tables.") parser_c.add_argument(''tablename'', nargs="+", help="The name(s) of the DB-Table to operate on.") parser_c.set_defaults(func=cmd_db_tables) args = parser.parse_args() args.func(args)


Aquí está la completa solución con un controlador de ayuda personalizado (casi todo el código de @Adaephon responde):

import argparse class _HelpAction(argparse._HelpAction): def __call__(self, parser, namespace, values, option_string=None): parser.print_help() # retrieve subparsers from parser subparsers_actions = [ action for action in parser._actions if isinstance(action, argparse._SubParsersAction)] # there will probably only be one subparser_action, # but better save than sorry for subparsers_action in subparsers_actions: # get all subparsers and print help for choice, subparser in subparsers_action.choices.items(): print("Subparser ''{}''".format(choice)) print(subparser.format_help()) parser.exit() # create the top-level parser parser = argparse.ArgumentParser(prog=''PROG'', add_help=False) # here we turn off default help action parser.add_argument(''--help'', action=_HelpAction, help=''help for help if you need some help'') # add custom help parser.add_argument(''--foo'', action=''store_true'', help=''foo help'') subparsers = parser.add_subparsers(help=''sub-command help'') # create the parser for the "a" command parser_a = subparsers.add_parser(''a'', help=''a help'') parser_a.add_argument(''bar'', type=int, help=''bar help'') # create the parser for the "b" command parser_b = subparsers.add_parser(''b'', help=''b help'') parser_b.add_argument(''--baz'', choices=''XYZ'', help=''baz help'') parsed_args = parser.parse_args()


Esto es un poco complicado, ya que argparse no expone una lista de sub-analizadores definidos directamente. Pero puede hacerse:

import argparse # create the top-level parser parser = argparse.ArgumentParser(prog=''PROG'') parser.add_argument(''--foo'', action=''store_true'', help=''foo help'') subparsers = parser.add_subparsers(help=''sub-command help'') # create the parser for the "a" command parser_a = subparsers.add_parser(''a'', help=''a help'') parser_a.add_argument(''bar'', type=int, help=''bar help'') # create the parser for the "b" command parser_b = subparsers.add_parser(''b'', help=''b help'') parser_b.add_argument(''--baz'', choices=''XYZ'', help=''baz help'') # print main help print(parser.format_help()) # retrieve subparsers from parser subparsers_actions = [ action for action in parser._actions if isinstance(action, argparse._SubParsersAction)] # there will probably only be one subparser_action, # but better save than sorry for subparsers_action in subparsers_actions: # get all subparsers and print help for choice, subparser in subparsers_action.choices.items(): print("Subparser ''{}''".format(choice)) print(subparser.format_help())

Este ejemplo debería funcionar para Python 2.7 y Python 3. El analizador de ejemplo es de la documentación de Python 2.7 en sub-comandos argparse .

Lo único que queda por hacer es agregar un nuevo argumento para la ayuda completa o reemplazar la ayuda incorporada en -h/--help .


También pude imprimir una breve ayuda para comandos usando _choices_actions .

def print_help(parser): print(parser.description) print(''/ncommands:/n'') # retrieve subparsers from parser subparsers_actions = [ action for action in parser._actions if isinstance(action, argparse._SubParsersAction)] # there will probably only be one subparser_action, # but better save than sorry for subparsers_action in subparsers_actions: # get all subparsers and print help for choice in subparsers_action._choices_actions: print('' {:<19} {}''.format(choice.dest, choice.help))


Tengo algunos envoltorios simples que almacenan varias referencias (Parser, SubParser, StoreAction) secuencialmente, para una fácil iteración durante la generación de ayuda.

Ahora me estoy organizando, generando verbos, resultados de ayuda generados automáticamente. Voy a publicar un resumen cuando tenga la oportunidad.

Hay un inconveniente, y eso tiene que ver con el contenido de ayuda generado en Argumentos opcionales: no es muy bueno. Mejorar estas salidas de ayuda llevará más que un envoltorio (si queremos mantenerlo limpio). Pero si desea una buena descripción general de ayuda para los programas en evolución, esto debería satisfacer a la mayoría.


Una forma más sencilla de iterar sobre los subparsers en el ejemplo de Adaephon es

for subparser in [parser_a, parser_b]: subparser.format_help()

Python te permite acceder a atributos ocultos como el parser._actions , pero eso no se recomienda. Es igual de fácil crear su propia lista al definir el analizador. Lo mismo vale para hacer cosas especiales con los argumentos. add_argument y add_subparser devuelven sus respectivos objetos Action y Parser por una razón.

Si estuviera haciendo una subclase de ArgumentParser me sentiría libre de usar _actions . Pero para una aplicación única, construir mi propia lista sería más claro.

Un ejemplo:

import argparse parser = argparse.ArgumentParser() parser.add_argument(''mainpos'') parser.add_argument(''--mainopt'') sp = parser.add_subparsers() splist = [] # list to collect subparsers sp1 = sp.add_parser(''cmd1'') splist.append(sp1) sp1.add_argument(''--sp1opt'') sp2 = sp.add_parser(''cmd2'') splist.append(sp2) sp2.add_argument(''--sp2opt'') # collect and display for helps helps = [] helps.append(parser.format_help()) for p in splist: helps.append(p.format_help()) print(''/n''.join(helps)) # or to show just the usage helps = [] helps.append(parser.format_usage()) for p in splist: helps.append(p.format_usage()) print(''''.join(helps))

La pantalla de ''uso'' combinado es:

usage: stack32607706.py [-h] [--mainopt MAINOPT] mainpos {cmd1,cmd2} ... usage: stack32607706.py mainpos cmd1 [-h] [--sp1opt SP1OPT] usage: stack32607706.py mainpos cmd2 [-h] [--sp2opt SP2OPT]

La visualización de las ayudas combinadas es larga y redundante. Puede editarse de varias maneras, ya sea después del formateo o con ayuda de formateadores especiales. Pero, ¿quién va a tomar tales decisiones?