inquirer python command-line user-interface

inquirer - python cmd



¿Implementando un estilo de interfaz de línea de comando "[comando][acción][parámetro]"? (6)

¿Cuál es la forma más "limpia" de implementar una interfaz de usuario de línea de comando, similar a la de git, por ejemplo:

git push origin/master git remote add origin git://example.com master

Lo ideal también es permitir un análisis más flexible, por ejemplo,

jump_to_folder app theappname v2 jump_to_folder app theappname source jump_to_folder app theappname source v2 jump_to_folder app theappname build v1 jump_to_folder app theappname build 1 jump_to_folder app theappname v2 build

jump_to_folder es el nombre de los scripts, la app es el comando, theappname es un parámetro de "ubicación fija", "build" y "v2" etc. son argumentos (por ejemplo, los posibles argumentos serían cualquier número / cualquier número con prefijo av, o build / source / tmp / config)

Podría analizar manualmente los argumentos con una serie de if / else / elifs , pero debe haber una forma más elegante de hacerlo.

Como un ejemplo completamente teórico, podría describir el esquema de UI ...

app: fixed: application_name optional params: arg subsection: "build" "source" "tmp" "config" arg version: integer "v" + integer

Luego, analice los argumentos proporcionados a través del esquema anterior y obtenga un diccionario:

>>> print schema.parse(["app", "theappname", "v1", "source"]) { "application_name": "theappname", "params":{ "subsection": "source", "version":"v1" } }

¿Existe tal sistema? Si no, ¿cómo podría implementar algo en esta línea?


argparse es perfecto para esto, específicamente "sub-comandos" y argumentos posicionales

import argparse def main(): arger = argparse.ArgumentParser() # Arguments for top-level, e.g "subcmds.py -v" arger.add_argument("-v", "--verbose", action="count", default=0) subparsers = arger.add_subparsers(dest="command") # Make parser for "subcmds.py info ..." info_parser = subparsers.add_parser("info") info_parser.add_argument("-m", "--moo", dest="moo") # Make parser for "subcmds.py create ..." create_parser = subparsers.add_parser("create") create_parser.add_argument("name") create_parser.add_argument("additional", nargs="*") # Parse opts = arger.parse_args() # Print option object for debug print opts if opts.command == "info": print "Info command" print "--moo was %s" % opts.moo elif opts.command == "create": print "Creating %s" % opts.name print "Additional: %s" % opts.additional else: # argparse will error on unexpected commands, but # in case we mistype one of the elif statements... raise ValueError("Unhandled command %s" % opts.command) if __name__ == ''__main__'': main()

Esto se puede usar así:

$ python subcmds.py create myapp v1 blah Namespace(additional=[''v1'', ''blah''], command=''create'', name=''myapp'', verbose=0) Creating myapp Additional: [''v1'', ''blah''] $ python subcmds.py info --moo usage: subcmds.py info [-h] [-m MOO] subcmds.py info: error: argument -m/--moo: expected one argument $ python subcmds.py info --moo 1 Namespace(command=''info'', moo=''1'', verbose=0) Info command --moo was 1


Aquí está mi sugerencia.

  1. Cambia tu gramática un poco.

  2. Use optparse.

Lo ideal también es permitir un análisis más flexible, por ejemplo,

jump_to_folder -n theappname -v2 cmd jump_to_folder -n theappname cmd source jump_to_folder -n theappname -v2 cmd source jump_to_folder -n theappname -v1 cmd build jump_to_folder -n theappname -1 cmd build jump_to_folder -n theappname -v2 cmd build

Entonces tienes 1 o 2 args: el comando es siempre el primer arg. Su argumento opcional es siempre el segundo arg.

Todo lo demás son opciones, sin ningún orden en particular.


Directamente de uno de mis guiones:

import sys def prog1_func1_act1(): print "pfa1" def prog2_func2_act2(): print "pfa2" commands = { "prog1 func1 act1": prog1_func1_act1, "prog2 func2 act2": prog2_func2_act2 } try: commands[" ".join(sys.argv[1:])]() except KeyError: print "Usage: ", commands.keys()

Es una solución bastante rápida y sucia, pero funciona muy bien para mi uso. Si tuviera que limpiarlo un poco, probablemente agregaría argparse a la mezcla para analizar argumentos posicionales y palabras clave.


Python tiene un módulo para analizar las opciones de línea de comando, optparse .


El módulo cmd probablemente funcionaría bien para esto.

Ejemplo:

import cmd class Calc(cmd.Cmd): def do_add(self, arg): print sum(map(int, arg.split())) if __name__ == ''__main__'': Calc().cmdloop()

Ejecutarlo:

$python calc.py (Cmd) add 4 5 9 (Cmd) help Undocumented commands: ====================== add help (Cmd)

Consulte los documentos Python o el sitio PyMOTW para obtener más información.