Argumentos de la l铆nea de comandos en Python

    Visi贸n general

    Dado que Python es un lenguaje de programaci贸n tan popular, adem谩s de tener soporte para la mayor铆a de los sistemas operativos, se ha vuelto ampliamente utilizado para crear herramientas de l铆nea de comandos para muchos prop贸sitos. Estas herramientas pueden abarcar desde aplicaciones CLI simples hasta aquellas m谩s complejas, como las de AWS awscli herramienta.

    Las herramientas complejas como esta suelen ser controladas por el usuario a trav茅s de argumentos de la l铆nea de comando, que permite al usuario usar comandos espec铆ficos, configurar opciones y m谩s. Por ejemplo, estas opciones podr铆an indicarle a la herramienta que genere informaci贸n adicional, lea datos de una fuente espec铆fica o env铆e la salida a una ubicaci贸n determinada.

    En general, los argumentos se pasan a las herramientas CLI de manera diferente, seg煤n su sistema operativo:

    • Tipo Unix: - seguido de una letra, como -ho -- seguido de una palabra, como --help
    • Windows: / seguido de una letra o una palabra, como /help

    Estos diferentes enfoques existen por razones hist贸ricas. Muchos programas en sistemas similares a Unix admiten la notaci贸n de guiones simples y dobles. La notaci贸n de un solo gui贸n se usa principalmente con opciones de una sola letra, mientras que los guiones dobles presentan una lista de opciones m谩s legible, que es particularmente 煤til para opciones complejas que deben ser m谩s expl铆citas.

    Nota: En este art铆culo nos centraremos 煤nicamente en el formato similar a Unix de - y --.

    Tenga en cuenta que tanto el nombre como el significado de un argumento son espec铆ficos de un programa; no existe una definici贸n general, aparte de algunas convenciones comunes como --help para obtener m谩s informaci贸n sobre el uso de la herramienta. Como desarrollador de un script de Python, usted decidir谩 qu茅 argumentos proporcionar a la persona que llama y qu茅 hacen. Esto requiere una evaluaci贸n adecuada.

    A medida que crece su lista de argumentos disponibles, su c贸digo se volver谩 m谩s complejo al tratar de analizarlos con precisi贸n. Afortunadamente, en Python hay varias bibliotecas disponibles para ayudarlo con esto. Cubriremos algunas de las soluciones m谩s comunes, que van desde “h谩galo usted mismo” con sys.argv, al enfoque “hecho para usted” con argparse.

    Manejo de argumentos de l铆nea de comandos con Python

    Python 3 admite varias formas diferentes de manejar los argumentos de la l铆nea de comandos. La forma incorporada es utilizar el sys m贸dulo. En t茅rminos de nombres y su uso, se relaciona directamente con la biblioteca C (libc). La segunda forma es la getopt m贸dulo, que maneja opciones tanto cortas como largas, incluida la evaluaci贸n de los valores de los par谩metros.

    Adem谩s, existen otros dos m茅todos comunes. Este es el m贸dulo argparse, que se deriva del optparse m贸dulo disponible hasta Python 2.7. El otro m茅todo es usar el docopt m贸dulo, que es disponible en GitHub.

    Cada una de estas formas tiene sus pros y sus contras, por lo que vale la pena evaluar cada una para ver cu谩l se adapta mejor a sus necesidades.

    El m贸dulo sys

    Este es un m贸dulo b谩sico que se envi贸 con Python desde los primeros d铆as. Toma un enfoque muy similar a la biblioteca C usando argc/argv para acceder a los argumentos. los m贸dulo sys implementa los argumentos de la l铆nea de comando en una estructura de lista simple llamada sys.argv.

    Cada elemento de la lista representa un solo argumento. El primer elemento de la lista, sys.argv[0], es el nombre de la secuencia de comandos de Python. El resto de los elementos de la lista, sys.argv[1] a sys.argv[n], son los argumentos de la l铆nea de comandos del 2 al n. Como delimitador entre los argumentos, se utiliza un espacio. Los valores de argumento que contienen un espacio en 茅l deben estar entre comillas para poder ser analizados correctamente por sys.

    El equivalente de argc es solo el n煤mero de elementos de la lista. Para obtener este valor, use Python len() operador. Mostraremos esto en un ejemplo de c贸digo m谩s adelante.

    Impresi贸n del primer argumento de CLI

    En este primer ejemplo, nuestro script determinar谩 la forma en que se llam贸. Esta informaci贸n se guarda en el primer argumento de la l铆nea de comandos, indexado con 0. El c贸digo siguiente muestra c贸mo obtiene el nombre de su secuencia de comandos de Python.

    import sys
    
    print ("The script has the name %s" % (sys.argv[0])
    

    Guarde este c贸digo en un archivo llamado argumentos-nombre-programa.py, y luego ll谩melo como se muestra a continuaci贸n. La salida es la siguiente y contiene el nombre del archivo, incluida su ruta completa:

    $ python arguments-program-name.py
    The script has the name arguments-program-name.py
    $ python /home/user/arguments-program-name.py
    The script has the name /home/user/arguments-program-name.py
    

    Como puede ver en la segunda llamada anterior, no solo obtenemos el nombre del archivo Python, sino tambi茅n la ruta completa utilizada para llamarlo.

    Contando el n煤mero de argumentos

    En este segundo ejemplo, simplemente contamos el n煤mero de argumentos de la l铆nea de comando usando el len() m茅todo. sys.argv es la lista que tenemos que examinar. En el siguiente c贸digo, obtenemos el n煤mero de argumentos y luego restamos 1 porque uno de esos argumentos (es decir, el primero) siempre se establece como el nombre del archivo, lo que no siempre nos resulta 煤til. Por lo tanto, el n煤mero real de argumentos pasados 鈥嬧媝or el usuario es len(sys.argv) - 1.

    import sys
    
    # Count the arguments
    arguments = len(sys.argv) - 1
    print ("The script is called with %i arguments" % (arguments))
    

    Guarde y asigne un nombre a este archivo argumentos-count.py. A continuaci贸n, se muestran algunos ejemplos de c贸mo llamar a este script. Esto incluye tres escenarios diferentes:

    • Una llamada sin m谩s argumentos de l铆nea de comando
    • Una llamada con dos argumentos
    • Una llamada con dos argumentos, donde el segundo es una cadena entre comillas que contiene un espacio
    $ python arguments-count.py
    The script is called with 0 arguments
    $ python arguments-count.py --help me
    The script is called with 2 arguments
    $ python arguments-count.py --option "long string"
    The script is called with 2 arguments
    
    Iterando a trav茅s de argumentos

    Nuestro tercer ejemplo genera todos los argumentos enviados al script de Python, excepto el nombre del programa en s铆. Por lo tanto, recorremos los argumentos de la l铆nea de comando comenzando con el segundo elemento de la lista. Recuerde que este es el 铆ndice 1 ya que las listas est谩n basadas en 0 en Python.

    import sys
    
    # Count the arguments
    arguments = len(sys.argv) - 1
    
    # Output argument-wise
    position = 1
    while (arguments >= position):
        print ("Parameter %i: %s" % (position, sys.argv[position]))
        position = position + 1
    

    A continuaci贸n, llamamos a nuestro c贸digo, que se guard贸 en el archivo argumentos-output.py. Como se hizo con nuestro ejemplo anterior, la salida ilustra tres llamadas diferentes:

    • Una llamada sin argumentos
    • Una llamada con dos argumentos
    • Una llamada con dos argumentos, donde el segundo argumento es una cadena entre comillas que contiene un espacio
    $ python arguments-output.py
    $ python arguments-output.py --help me
    Parameter 1: --help
    Parameter 2: me
    $ python arguments-output.py --option "long string"
    Parameter 1: --option
    Parameter 2: long string
    

    Recuerde, el objetivo de mostrar el ejemplo de cadena entre comillas es que los par谩metros generalmente est谩n delimitados por un espacio, a menos que est茅n entre comillas.

    El m贸dulo getopt

    Como habr谩s notado antes, el sys El m贸dulo divide la cadena de la l铆nea de comando en facetas 煤nicas solamente. El python m贸dulo getopt va un poco m谩s all谩 y ampl铆a la separaci贸n de la cadena de entrada mediante la validaci贸n de par谩metros. Basado en el getopt Funci贸n C, permite opciones tanto cortas como largas, incluida una asignaci贸n de valor.

    En la pr谩ctica, requiere sys m贸dulo para procesar correctamente los datos de entrada. Para hacerlo, tanto el sys m贸dulo y el getopt El m贸dulo debe cargarse de antemano. A continuaci贸n, de la lista de par谩metros de entrada eliminamos el primer elemento de la lista (consulte el c贸digo a continuaci贸n) y almacenamos la lista restante de argumentos de la l铆nea de comando en la variable llamada argument_list.

    # Include standard modules
    import getopt, sys
    
    # Get full command-line arguments
    full_cmd_arguments = sys.argv
    
    # Keep all but the first
    argument_list = full_cmd_arguments[1:]
    
    print argument_list
    

    Los argumentos en argument_list ahora se puede analizar usando el getopts() m茅todo. Pero antes de hacer eso, tenemos que decir getopts() sobre qu茅 par谩metros son v谩lidos. Se definen as铆:

    short_options = "ho:v"
    long_options = ["help", "output=", "verbose"]
    

    Esto significa que estos argumentos son los que consideramos v谩lidos, junto con informaci贸n adicional:

    ------------------------------------------
    long argument   short argument  with value
    ------------------------------------------
    --help           -h              no
    --output         -o              yes
    --verbose        -v              no
    ------------------------------------------
    

    Puede que hayas notado que el o la opci贸n corta fue precedida por dos puntos, :. Esto dice getopt que a esta opci贸n se le debe asignar un valor.

    Esto ahora nos permite procesar una lista de argumentos. los getopt() El m茅todo requiere que se configuren tres par谩metros: la lista de argumentos reales de argv, as铆 como las opciones v谩lidas cortas y largas (que se muestran en el fragmento de c贸digo anterior).

    La llamada al m茅todo en s铆 se mantiene en una declaraci贸n try-catch para cubrir errores durante la evaluaci贸n. Se genera una excepci贸n si se descubre un argumento que no forma parte de la lista como se defini贸 anteriormente. La secuencia de comandos de Python imprimir谩 el mensaje de error en la pantalla y saldr谩 con el c贸digo de error 2.

    try:
        arguments, values = getopt.getopt(argument_list, short_options, long_options)
    except getopt.error as err:
        # Output error, and return with an error code
        print (str(err))
        sys.exit(2)
    

    Finalmente, los argumentos con los valores correspondientes se almacenan en las dos variables denominadas arguments y values. Ahora, puede evaluar f谩cilmente estas variables en su c贸digo. Podemos usar un for-loop para recorrer la lista de argumentos reconocidos, una entrada despu茅s de la siguiente.

    # Evaluate given options
    for current_argument, current_value in arguments:
        if current_argument in ("-v", "--verbose"):
            print ("Enabling verbose mode")
        elif current_argument in ("-h", "--help"):
            print ("Displaying help")
        elif current_argument in ("-o", "--output"):
            print (("Enabling special output mode (%s)") % (current_value))
    

    A continuaci贸n, puede ver el resultado de ejecutar este c贸digo. Mostraremos c贸mo reacciona el programa con argumentos de programa v谩lidos y no v谩lidos:

    $ python arguments-getopt.py -h
    Displaying help
    $ python arguments-getopt.py --help
    Displaying help
    $ python arguments-getopt.py --output=green --help -v
    Enabling special output mode (green)
    Displaying help
    Enabling verbose mode
    $ python arguments-getopt.py -verbose
    option -e not recognized
    

    La 煤ltima llamada a nuestro programa puede parecer un poco confusa al principio. Para comprenderlo, debe saber que las opciones abreviadas (a veces tambi茅n llamadas banderas) se pueden usar junto con un solo gui贸n. Esto permite que su herramienta acepte muchas opciones m谩s f谩cilmente. Por ejemplo, llamando python arguments-getopt.py -vh es lo mismo que llamar python arguments-getopt.py -v -h. Entonces, en la 煤ltima llamada anterior, el getopt m贸dulo pens贸 que el usuario estaba intentando pasar -e como una opci贸n, que no es v谩lida.

    El m贸dulo argparse

    los m贸dulo argparse ha estado disponible desde Python 3.2, y una mejora de la optparse m贸dulo que existe hasta Python 2.7. La documentaci贸n de Python contiene una descripci贸n de la API y un tutorial que cubre todos los m茅todos en detalle.

    El m贸dulo ofrece una interfaz de l铆nea de comandos con una salida estandarizada, mientras que las dos primeras soluciones dejan gran parte del trabajo en sus manos. argparse permite la verificaci贸n de argumentos fijos y opcionales, con la verificaci贸n de nombres como estilo corto o largo. Como argumento opcional predeterminado, incluye -h, junto con su versi贸n larga --help. Este argumento va acompa帽ado de un mensaje de ayuda predeterminado que describe los argumentos aceptados.

    El siguiente c贸digo muestra la inicializaci贸n del analizador y la salida a continuaci贸n que muestra la llamada b谩sica, seguida del mensaje de ayuda. A diferencia de las llamadas de Python que usamos en los ejemplos anteriores, tenga en cuenta que debe usar Python 3 con estos ejemplos.

    # Include standard modules
    import argparse
    
    # Initiate the parser
    parser = argparse.ArgumentParser()
    parser.parse_args()
    
    $ python3 arguments-argparse-basic.py 
    $ python3 arguments-argparse-basic.py -h
    usage: arguments-argparse-basic.py [-h]
    
    optional arguments:
      -h, --help  show this help message and exit
    $ python3 arguments-argparse-basic.py --verbose
    usage: arguments-argparse-basic.py [-h]
    arguments-argparse-basic.py: error: unrecognized arguments: --verbose
    

    En el siguiente paso, agregaremos una descripci贸n personalizada al mensaje de ayuda para nuestros usuarios. Inicializar el analizador de esta forma permite un texto adicional. El siguiente c贸digo almacena la descripci贸n en el text variable, que se da expl铆citamente a la argparse clase como el description par谩metro. Al llamar a este c贸digo a continuaci贸n, puede ver c贸mo se ve la salida.

    # Include standard modules
    import argparse
    
    # Define the program description
    text="This is a test program. It demonstrates how to use the argparse module with a program description."
    
    # Initiate the parser with a description
    parser = argparse.ArgumentParser(description=text)
    parser.parse_args()
    
    $ python3 arguments-argparse-description.py --help
    usage: arguments-argparse-description.py [-h]
    
    This is a test program. It demonstrates how to use the argparse module with a
    program description.
    
    optional arguments:
      -h, --help  show this help message and exit
    

    Como paso final, agregaremos un argumento opcional llamado -V, que tiene un argumento de estilo largo correspondiente llamado --version. Para hacerlo usamos el m茅todo add_argument() que llamamos con tres par谩metros (mostrados para --version, solamente):

    • El nombre del par谩metro: --version
    • El texto de ayuda para el par谩metro: help="show program version"
    • Acci贸n (sin valor adicional): action="store_true"

    El c贸digo fuente para eso se muestra a continuaci贸n. Leer los argumentos en la variable llamada args se realiza a trav茅s del parse_args() m茅todo del parser objeto. Tenga en cuenta que env铆a tanto la versi贸n corta como la versi贸n larga en una llamada. Finalmente, verifica si los atributos args.V o args.version se establecen y emiten el mensaje de versi贸n.

    # Include standard modules
    import argparse
    
    # Initiate the parser
    parser = argparse.ArgumentParser()
    parser.add_argument("-V", "--version", help="show program version", action="store_true")
    
    # Read arguments from the command line
    args = parser.parse_args()
    
    # Check for --version or -V
    if args.version:
        print("This is myprogram version 0.1")
    
    $ python3 arguments-argparse-optional.py -V
    This is myprogram version 0.1
    $ python3 arguments-argparse-optional.py --version
    This is myprogram version 0.1
    

    los --version El argumento no requiere que se d茅 un valor en la l铆nea de comando. Es por eso que establecemos el argumento de acci贸n en "store_true". En otros casos, es posible que necesite un valor asignado adicional, por ejemplo, si especifica un cierto volumen, altura o ancho. Esto se muestra en el siguiente ejemplo. Como caso predeterminado, tenga en cuenta que todos los argumentos se interpretan como cadenas.

    # Include standard modules
    import argparse
    
    # Initiate the parser
    parser = argparse.ArgumentParser()
    
    # Add long and short argument
    parser.add_argument("--width", "-w", help="set output width")
    
    # Read arguments from the command line
    args = parser.parse_args()
    
    # Check for --width
    if args.width:
        print("Set output width to %s" % args.width)
    

    Aqu铆 mostramos lo que sucede al enviar diferentes valores de argumento. Esto incluye tanto la versi贸n corta como la larga, as铆 como el mensaje de ayuda.

    $ python3 arguments-argparse-optional2.py -w 10
    Set output width to 10
    $ python3 arguments-argparse-optional2.py --width 10
    Set output width to 10
    $ python3 arguments-argparse-optional2.py -h
    usage: arguments-argparse-optional2.py [-h] [--width WIDTH]
    
    optional arguments:
      -h, --help            show this help message and exit
      --width WIDTH, -w WIDTH
                            set output width
    

    Conclusi贸n

    En este art铆culo mostramos muchos m茅todos diferentes para recuperar argumentos de l铆nea de comando en Python, incluido el uso de sys, getopty argparse. Estos m贸dulos var铆an en funcionalidad, algunos brindan mucho m谩s que otros. sys es totalmente flexible, mientras que tanto getopty argparse requieren algo de estructura. Por el contrario, cubren la mayor parte del trabajo complejo que sys deja en tus manos. Despu茅s de trabajar con los ejemplos proporcionados, deber铆a poder determinar qu茅 m贸dulo se adapta mejor a su proyecto.

    En este art铆culo no hablamos de otras soluciones como la docopts m贸dulo, lo acabamos de mencionar. Este m贸dulo sigue un enfoque totalmente diferente y se explicar谩 en detalle en uno de los pr贸ximos art铆culos.

    Referencias

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *