Generaci贸n de interfaces de l铆nea de comandos (CLI) con Fire en Python

    Introducci贸n

    UN Interfaz de l铆nea de comandos (CLI) es una forma de interactuar con las computadoras mediante comandos textuales.

    Muchas herramientas que no requieren GUI est谩n escritas como herramientas / utilidades CLI. Aunque Python tiene incorporado argparse m贸dulo, existen otras bibliotecas con funciones similares.

    Estas bibliotecas pueden ayudarnos a escribir secuencias de comandos CLI, proporcionando servicios como opciones de an谩lisis y marcas para una funcionalidad CLI mucho m谩s avanzada.

    Este art铆culo analiza el Fuego de python biblioteca, escrita por Google Inc., una herramienta 煤til para crear CLI con c贸digo m铆nimo.

    Forma general de aplicaciones CLI

    Antes de empezar con el Fire biblioteca intentemos comprender los conceptos b谩sicos de los programas de interfaz de l铆nea de comandos en general. Dependiendo del programa y comando, el patr贸n general de una CLI se puede resumir de la siguiente manera:

    prompt command parameter1 parameter2 ... parameterN
    
    • r谩pido es una secuencia de caracteres que indicaciones el usuario para ingresar un comando
    • mando es el nombre del programa que el usuario est谩 ejecutando (p. ej. ls)
    • par谩metros son tokens opcionales que aumentan o modifican la salida del comando

    Un programa CLI se ejecuta escribiendo el nombre del programa despu茅s de la prompt aparece, en este caso el PS s铆mbolo.

    Aqu铆 estamos usando el ls comando que devuelve una lista de nombres de archivos en un directorio, siendo el directorio actual el predeterminado:

    $ ls
    README.md
    python
    

    Puede modificar el comportamiento o la salida de un programa de l铆nea de comandos proporcion谩ndole una lista de tokens o par谩metros m谩s conocidos como banderas. Probemos una bandera del ls mando:

    $ ls -l
    -rwxrwxrwx 1 pandeytapan pandeytapan  10 Sep 23 18:29 README.md
    drwxrwxrwx 1 pandeytapan pandeytapan 512 Sep 23 18:29 python
    

    Como puede ver, despu茅s de pasar el -l , obtenemos informaci贸n adicional para cada entrada, como el propietario, el grupo y el tama帽o del archivo.

    Banderas que tienen un solo guion (-) se denominan opciones cortas, mientras que aquellas con dos guiones (--) se denominan opciones largas. Ambos tipos se pueden usar juntos en un solo comando, como en el siguiente ejemplo:

    $ ls -l --time-style=full-iso
    -rwxrwxrwx 1 pandeytapan pandeytapan  10 2020-09-23 18:29:25.501149000 +0530 README.md
    drwxrwxrwx 1 pandeytapan pandeytapan 512 2020-09-23 18:29:25.506148600 +0530 python
    

    La diferencia entre opciones cortas y largas:

    • Las opciones cortas se pueden encadenar juntas
      • Si queremos usar tanto el -l y -a opciones cortas que simplemente escribimos -al
    • Las opciones cortas se indican con un solo car谩cter, mientras que las opciones largas tienen un nombre completo separado por guiones y no se pueden encadenar.

    los --time-style bandera funciona con el -l marca y controla el formato de tiempo de visualizaci贸n para una lista de directorios.

    Una CLI proporciona una manera f谩cil para que el usuario configure y ejecute una aplicaci贸n desde la l铆nea de comandos. La biblioteca Python Fire de Google facilita la adici贸n de un componente de procesamiento CLI a cualquier script Python existente.

    Veamos c贸mo hacer una aplicaci贸n de l铆nea de comandos usando Python Fire.

    Instalaci贸n

    Sigamos e instalemos la biblioteca usando pip:

    $ pip install fire
    

    Python Fire funciona en cualquier objeto de Python, es decir, funciones, clases, diccionarios, listas, etc. Tratemos de comprender el uso de Python Fire biblioteca a trav茅s de algunos ejemplos.

    Generando una aplicaci贸n CLI con Python Fire

    Hagamos un gui贸n, digamos, fire_cli.py y poner una funci贸n dentro de 茅l:

    def greet_mankind():
        """Greets you with Hello World"""
        return 'Hello World'
    

    Al ejecutar este programa en el shell de Python, el resultado es:

    >>> from fire_cli import greet_mankind
    >>> greet_mankind()
    'Hello World'
    >>>
    

    Podemos convertir f谩cilmente este script en una aplicaci贸n CLI usando Python Fire:

    import fire
    
    def greet_mankind():
        """
        Returns a textual message
        """
        return 'Hello World'
    
    if __name__ == '__main__':
        fire.Fire()
    

    los fire.Fire() llamadas convierte el m贸dulo es decir fire_cli.py en una aplicaci贸n Fire CLI. Adem谩s, ha expuesto la greet_mankind() funciona como comando, autom谩ticamente.

    Ahora podemos guardar y ejecutar el script anterior como CLI de la siguiente manera:

    $ python fire_greet_mk_cli.py greet_mankind
    Hello World
    

    Como recordatorio, analicemos la llamada:

    • PS es el aviso
    • python es el int茅rprete de comandos
    • fire_cli.py es el m贸dulo que contiene el comando CLI
    • saludar a la humanidad es el comando

    Pasar argumentos a un comando

    Creemos otra aplicaci贸n CLI que tome un nombre como par谩metro y muestre un mensaje de saludo personalizado:

    import fire
    
    def greetings(name):
        '''
        Returns a greeting message
        Parameters
        ----------
        name : string
            String that represents the addresses name 
    
        Returns
        -------
        string
            greeting message concatenated with name
        '''
        return 'Hello %s' % name
    
    if __name__ == '__main__':
        fire.Fire()
    

    Aqu铆, ahora tenemos una funci贸n que acepta una cadena: name. Python Fire recoge esto autom谩ticamente y si proporcionamos un argumento despu茅s de greetings llamar, vincular谩 esa entrada a la name par谩metro. Tambi茅n hemos agregado un comentario como una especie de documentaci贸n para el --help mando.

    As铆 es como podemos ejecutar este comando desde la l铆nea de comandos:

    $ python fire_greet_cli.py greetings Robin
    Hello Robin
    

    Una aplicaci贸n Fire CLI puede usar --help banderas para verificar la descripci贸n del comando generada a partir de los documentos de Python:

    python fire_greet_cli.py greetings --help
    NAME
        fire_greet_cli.py greetings - Returns a greeting message
    
    SYNOPSIS
        fire_greet_cli.py greetings NAME
    
    DESCRIPTION
        Returns a greetings message
    
    POSITIONAL ARGUMENTS
        NAME
            String that represents the addresses name
    
    NOTES
        You can also use flags syntax for POSITIONAL ARGUMENTS
    

    Establecer una funci贸n como punto de entrada

    Con una ligera modificaci贸n podemos controlar la exposici贸n del greetings() funci贸n a la l铆nea de comandos y configurarlo como el punto de entrada predeterminado:

    import fire
    
    def greetings(name):
        '''
        Returns a greeting message 
        :param name: string argument
        :return: greeting message appended with name
        '''
        return 'Hello %s' % name
    
    if __name__ == '__main__':
        fire.Fire(greetings)
    

    As铆 es como ejecutaremos el comando ahora:

    $ python fire_greet_cli.py Robin
    Hello Robin
    

    Entonces esta vez ya no necesitamos llamar al comando como lo hemos definido greetings impl铆citamente como un punto de entrada usando Fire(). Una cosa a tener en cuenta aqu铆 es que con esta versi贸n, solo podemos pasar un 煤nico argumento :

    $ python fire_greet_cli.py Robin Hood
    ERROR: Could not consume arg: Hood
    ...
    $ python fire_greet_cli.py Robin
    Hello Robin
    

    An谩lisis de argumentos

    La biblioteca de Fire tambi茅n funciona con clases. Definamos una clase CustomSequence que genera y devuelve una lista de n煤meros entre start y end:

    import fire
    
    class CustomSequence:
        '''Class that generates a sequence of numbers'''
        def __init__(self, offset=1):
            '''
             Parameters
            ----------
            offset : int, optional
                Number controlling the difference between two generated values
            '''
            self.offset = offset
    
        def generate(self, start, stop):
            '''
            Generates the sequence of numbers
    
            Parameters
            ----------
            start : int
                Number that represents the elements lower bound
            stop : int
                Number that represents the elements upper bound
    
            Returns
            -------
            string
                a string that represents the generated sequence
            '''
            return ' '.join(str(item) for item in range(start, stop, self.offset))
    
    if __name__ == '__main__':
        fire.Fire(CustomSequence)
    

    As铆 es como generamos una secuencia usando esta utilidad de l铆nea de comandos:

    $ python fire_gen_cli.py generate 1 10
    1 2 3 4 5 6 7 8 9
    

    Usamos una clase en lugar de una funci贸n porque, a diferencia de las funciones, si queremos pasar un argumento al constructor, siempre debe representarse como una bandera de l铆nea de comando con guiones dobles (p. Ej. --offset=2).

    Por lo tanto, nuestra aplicaci贸n CLI admite un argumento opcional --offset que se pasar谩 al constructor de la clase. Esto modifica la salida controlando la diferencia entre dos valores generados consecutivamente:

    Aqu铆 est谩 la salida con un valor de compensaci贸n de 2:

    $ python fire_gen_cli.py generate 1 10 --offset=2
    1 3 5 7 9
    

    Los argumentos del constructor siempre se pasan usando la sintaxis de la bandera, mientras que los argumentos a otros m茅todos o funciones se pasan posicionalmente o por nombre:

    $ python fire_gen_cli.py generate --start=10 --stop=20
    10 11 12 13 14 15 16 17 18 19
    $ python fire_gen_cli.py generate 10 20
    10 11 12 13 14 15 16 17 18 19
    $ python fire_gen_cli.py generate --start=10 --stop=20 --offset=2
    10 12 14 16 18
    

    Podemos comprobar el uso delgenerate comando usando el --help bandera. Esto le dar谩 la informaci贸n de uso para la CLI:

    $ python fire_gen_cli.py generate --help
    INFO: Showing help with the command 'fire_gen_cli.py generate -- --help'.
    
    NAME
        fire_gen_cli.py generate - Generates the sequence of numbers
    
    SYNOPSIS
        fire_gen_cli.py generate START STOP
    
    DESCRIPTION
        Generates the sequence of numbers
    
    POSITIONAL ARGUMENTS
        START
            Number that represents the first value for the sequence
        STOP
            Number that represents the ending value for the sequence
    
    NOTES
        You can also use flags syntax for POSITIONAL ARGUMENTS
    

    Utilizando --help con el m贸dulo nos da su informaci贸n de uso:

    $ python fire_gen_cli.py  --help
    INFO: Showing help with the command 'fire_gen_cli.py -- --help'.
    
    NAME
        fire_gen_cli.py - Class that generates a sequence of numbers
    
    SYNOPSIS
        fire_gen_cli.py <flags>
    
    DESCRIPTION
        Class that generates a sequence of numbers
    
    FLAGS
        --offset=OFFSET
    

    Banderas de fuego

    Fire CLI viene con muchos indicadores integrados. Ya hemos visto --helpSin embargo, otra bandera 煤til es --interactive. El uso de esta bandera nos pone en modo Python REPL, con el m贸dulo ya definido.

    Esto es bastante 煤til para probar comandos:

    $ python fire_greet_cli.py -- --interactive
    Fire is starting a Python REPL with the following objects:
    Modules: fire
    Objects: component, fire_greet_cli.py, greetings, result, trace
    
    Python 3.7.8 (tags/v3.7.8:4b47a5b6ba, Jun 28 2020, 08:53:46) [MSC v.1916 64 bit (AMD64)]
    Type 'copyright', 'credits' or 'license' for more information
    IPython 7.16.1 -- An enhanced Interactive Python. Type '?' for help.
    
    
    In [1]: greetings("Robin")
    Out[1]: 'Hello Robin'
    

    Tenga en cuenta que las banderas de fuego deben separarse de otras opciones con dos guiones (--), as铆 que si queremos usar ambos --help y --interactive banderas en un comando, se ver铆a as铆:

    $ python fire_greet_cli.py -- --help --interactive
    

    Conclusi贸n

    La biblioteca Python Fire de Google es una forma r谩pida y f谩cil de generar interfaces de l铆nea de comandos (CLI) para casi cualquier objeto Python.

    En este art铆culo, hemos repasado c贸mo instalar Python Fire, as铆 como tambi茅n c贸mo generar interfaces de l铆nea de comandos simples.

     

    Etiquetas:

    Deja una respuesta

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