Hacemos amigos de Python y Bash: bibliotecas smart-env y python-shell

Buen día a todos.

Hoy, Python es uno de los lenguajes más utilizados en el campo de la creación no solo de productos de software directamente, sino también de proporcionar su infraestructura. Como resultado, muchos devops, por su voluntad o en su contra, tuvieron que aprender un nuevo idioma para usarlo posteriormente como complemento de los buenos y viejos scripts de Bash. Sin embargo, Bash y Python profesan diferentes enfoques para escribir código y tienen ciertas características, en vista de que portar los scripts de Bash al "lenguaje serpiente" a veces es espacioso y está lejos de ser una tarea trivial.

Para facilitar la vida de los desarrolladores, se han creado y se siguen creando muchas bibliotecas y utilidades útiles en Python. Este artículo describe inmediatamente dos nuevas bibliotecas creadas por el autor de esta publicación: smart-envy python-shell , y diseñado para salvar a los desarrolladores de la necesidad de prestar mucha atención a las complejidades de trabajar con Python, dejando espacio para tareas más interesantes. El alcance de la biblioteca son las variables de entorno y el lanzamiento de utilidades externas.

¿Quiénes están interesados, por favor, debajo del gato?

Bicicletas nuevas?


Parecería, ¿por qué crear nuevos paquetes para operaciones bastante mundanas? ¿Qué impide el uso directo de os.environ y subproceso. <Método o clase de su elección>?

Daré evidencia a favor de cada una de las bibliotecas por separado.

Biblioteca inteligente-env


Antes de escribir su propia creación, es útil navegar por Internet y buscar soluciones listas para usar. Por supuesto, existe el riesgo de no encontrar lo que necesita, sino que es un "caso de seguro". Como regla general, el enfoque funciona y ahorra mucho tiempo y esfuerzo.

Según los resultados de la búsqueda , se revelaron los siguientes:

  • hay paquetes que realmente envuelven llamadas a os.environ, pero al mismo tiempo requieren un montón de acciones de distracción (creando una instancia de la clase, parámetros especiales en llamadas, etc.);
  • Sin embargo, hay buenos paquetes que están estrechamente vinculados a un ecosistema específico (principalmente marcos web como Django) y, por lo tanto, no son universales sin un archivo;
  • Hay raros intentos de hacer algo nuevo. Por ejemplo, agregue tipeo y analice explícitamente valores variables llamando a métodos del formulario

    get_<typename>(var_name)

    O aquí hay otra solución que, sin embargo, actualmente no admite Python 2 deshonrado (en el cual, a pesar del RIP oficial , todavía hay montañas de código escrito y ecosistemas completos);
  • hay manualidades entre estudiantes y escuelas, no está nada claro por qué terminaron en el PyPI aguas arriba y solo crean problemas al nombrar nuevos paquetes (en particular, el nombre "smart-env" es una medida necesaria).

Y la lista sigue y sigue ... Sin embargo, los puntos anteriores fueron suficientes para captar la idea de hacer algo conveniente y universal.

Requisitos para smart-env:

  • El esquema de uso más simple
  • Soporte de escritura de datos fácilmente configurable
  • Python 2.7 compatible
  • Buena cobertura de prueba

Al final, todo esto se realizó. Aquí hay un ejemplo de uso:

from smart_env import ENV

print(ENV.HOME)  # Equals print(os.environ['HOME'])

# assuming you set env variable MYVAR to "True"

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Equals boolean True

ENV.NEW_VAR = 100  # Sets a new environment variable

Como puede ver en el ejemplo, para trabajar con la nueva clase es suficiente importarla (no es necesario crear una instancia, menos la acción adicional). El acceso a cualquier variable de entorno se logra al referirse a ella como una variable de clase ENV, que, de hecho, hace de esta clase un envoltorio intuitivo para el entorno del sistema nativo, convirtiéndola simultáneamente en una posible variante del objeto de configuración de casi cualquier sistema (un enfoque similar, por ejemplo, se logra en Django , solo allí el objeto de configuración es directamente el paquete de módulo / configuración).

La activación / desactivación del modo de soporte de escritura automática se logra mediante dos métodos: enable_automatic_type_cast () y disable_automatic_type_cast (). Esto puede ser conveniente si la variable de entorno contiene un objeto similar a JSON serializado o incluso solo una constante booleana (uno de los casos más comunes es establecer explícitamente la variable DEBUG en Django comparando la variable de entorno con cadenas "válidas"). Pero ahora no hay necesidad de convertir explícitamente las líneas: la mayoría de las acciones necesarias ya están incrustadas en las entrañas de la biblioteca y solo esperan una señal para la acción. :) En general, la escritura funciona de forma transparente y admite casi todos los tipos de datos integrados disponibles (no se han probado los conjuntos congelados, complejos y bytes).

El requisito de soporte para Python 2 se implementó prácticamente sin sacrificios (abandonando el tipeo y algunos dulces de azúcar en versiones recientes de Python 3), en particular, gracias a los seis omnipresentes (para resolver los problemas del uso de metaclases).

Pero hay algunas limitaciones:

  • El soporte para Python 3 implica la versión 3.5 y superior (su presencia en su proyecto es el resultado de la pereza o la falta de necesidad de mejoras, porque es difícil encontrar una razón objetiva por la que todavía está en la versión 3.4);
  • En Python 2.7, la biblioteca no admite la deserialización de literales establecidos. Descripción aquí . Pero, si alguien quiere implementarlo, bienvenido :);

La biblioteca también profesa un mecanismo de excepción en caso de errores de análisis. Si una cadena no puede ser reconocida por ninguno de los analizadores disponibles, el valor permanece cadena (más bien, por razones de conveniencia y compatibilidad con la lógica habitual de las variables en Bash).

Biblioteca Python-shell


Ahora hablaré sobre la segunda biblioteca (omitiré la descripción de las deficiencias de los análogos disponibles, es similar a la descrita para smart-env. Analogs, aquí y aquí ).

En general, la idea de implementación y los requisitos para ella son similares a los descritos para smart-env, como se puede ver en el ejemplo:

from python_shell import Shell

Shell.ls('-l', '$HOME')  # Equals "ls -l $HOME"

command = Shell.whoami()  # Equals "whoami"
print(command.output)  # prints your current user name

print(command.command)  # prints "whoami"
print(command.return_code)  # prints "0"
print(command.arguments)  # prints ""

Shell.mkdir('-p', '/tmp/new_folder')  # makes a new folder

La idea es esta:

  1. Una sola clase que representa Bash en el mundo de Python;
  2. Cada comando Bash se llama en función de la clase Shell;
  3. Los parámetros de llamada de cada función se reenvían a la llamada al comando Bash correspondiente;
  4. Cada comando se ejecuta "aquí y ahora" en el momento de su llamada, es decir trabaja enfoque sincrónico;
  5. es posible acceder al comando de escape en stdout, así como a su código de retorno;
  6. Si el comando está ausente en el sistema, se produce una excepción.

Al igual que con smart-env, se proporciona soporte para Python 2 (aunque tomó un poco más de sangre de sacrificio) y no hay soporte para Python 3.0-3.4.

Planes de desarrollo de la biblioteca


Puede usar las bibliotecas ahora: ambas se presentan en el PyPI oficial. Las fuentes están disponibles en Github (ver más abajo).

Ambas bibliotecas se desarrollarán teniendo en cuenta los comentarios recopilados de los interesados. Y, si en smart-env puede ser difícil encontrar una variedad de nuevas características, definitivamente hay algo más que agregar en python-shell:

  • soporte para llamadas sin bloqueo;
  • la posibilidad de comunicación interactiva con el equipo (trabajar con stdin);
  • agregar nuevas propiedades (por ejemplo, propiedad para obtener el escape de stderr);
  • implementación del catálogo de comandos disponibles (para usar con la función dir ())
  • etc.

Referencias


  1. Biblioteca inteligente-env: Github y PyPI
  2. Biblioteca Python-shell: github y pypi
  3. Canal de Telegram para actualizaciones de la biblioteca


UPD 23/02/2020:
* Los repositorios se han movido, los enlaces correspondientes se han actualizado
* La versión de python-shell == 1.0.1 se está preparando para su lanzamiento el 29/02/2020. Entre los cambios están el soporte para el autocompletado de comandos y el comando dir (Shell), el lanzamiento de comandos con un identificador inválido de Python y la corrección de errores.

UPD 03/01/2020:
* Publicar en el próximo lanzamiento.

All Articles