Haciendo amistad entre Python y Bash: bibliotecas smart-env y python-shell

Buen dia a todos.

Hoy en día, Python es uno de los lenguajes más utilizados en el campo de la creación no solo de productos de software, sino también de su infraestructura. Como resultado, muchos desarrolladores, ya sea por su voluntad o en contra, tuvieron que aprender un nuevo lenguaje para usarlo más tarde como complemento a los viejos scripts Bash. Sin embargo, Bash y Python profesan enfoques diferentes para escribir código y tienen ciertas características, lo que significa que trasladar scripts de Bash al "lenguaje de serpiente" a veces resulta ser una tarea amplia y nada trivial.

Para hacer la vida más fácil a los desarrolladores, se han creado y se siguen creando muchas bibliotecas y utilidades útiles en Python. Este artículo describe dos nuevas bibliotecas creadas por el autor de esta publicación: entorno inteligente и caparazón de pitón - y diseñado para aliviar 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 ámbito de actividad de las bibliotecas son las variables de entorno y el lanzamiento de utilidades externas.

Cualquier persona interesada, consulte cat.

¿Nuevas "bicicletas"?

Al parecer, ¿por qué crear nuevos paquetes para operaciones bastante normales? ¿Qué le impide utilizar os.environ y subprocess.<método o clase de su elección> directamente?

Proporcionaré pruebas a favor de cada una de las bibliotecas por separado.

biblioteca de entorno inteligente

Antes de escribir su propia creación, es útil conectarse a Internet y buscar soluciones ya preparadas. Por supuesto, existe el riesgo de no encontrar lo que necesita, pero esto es más bien un "evento seguro". Como regla general, este enfoque funciona y ahorra mucho tiempo y esfuerzo.

Segun los resultados buscar se reveló lo siguiente:

  • hay paquetes que en realidad envuelven llamadas a os.environ, pero al mismo tiempo requieren un montón de acciones que distraen (crear una instancia de una clase, parámetros especiales en las llamadas, etc.);
  • Hay buenos paquetes que, sin embargo, están estrictamente ligados a un ecosistema específico (principalmente frameworks web como Django) y por lo tanto no son universales sin un archivo;
  • Hay raros intentos de hacer algo nuevo. Por ejemplo, agregar mecanografía y analizar explícitamente valores de variables llamando a métodos como
    get_<typename>(var_name)

    O aqui una solucion mas, que, sin embargo, no es compatible con el ahora deshonrado Python 2 (que, a pesar de QEPD oficial, todavía hay montañas de código escrito y ecosistemas enteros);

  • Hay manualidades de estudiantes de escuela que, por alguna razón desconocida, terminaron en PyPI ascendente y solo crean problemas con el nombre de nuevos paquetes (en particular, el nombre "smart-env" es una medida necesaria).

Y esta lista puede durar mucho tiempo. Sin embargo, los puntos anteriores fueron suficientes para entusiasmarme con la idea de hacer algo conveniente y universal.

Requisitos que se establecieron antes de escribir smart-env:

  • El esquema de uso más simple.
  • Soporte de escritura de datos fácilmente configurable
  • Compatible con Python 2.7
  • Buena cobertura de código mediante pruebas.

Al final, todo esto se hizo realidad. A continuación se muestra 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 una nueva clase, sólo necesita importarla (no necesita crear una instancia, menos la acción adicional). El acceso a cualquier variable de entorno se logra refiriéndose a ella como una variable de la clase ENV, lo que, de hecho, convierte a esta clase en un contenedor intuitivo para el entorno nativo del sistema, al mismo tiempo que la convierte en un posible objeto de configuración para casi cualquier sistema ( un enfoque similar, por ejemplo, se logra en Django, solo que allí el objeto de configuración es el módulo/paquete de configuración en sí).

Habilitar/deshabilitar el modo de soporte de escritura automática se logra usando dos métodos: enable_automatic_type_cast() y enable_automatic_type_cast(). Esto puede ser conveniente si la variable de entorno contiene un objeto tipo JSON serializado o incluso simplemente una constante booleana (establecer explícitamente la variable DEBUG en Django comparando la variable de entorno con cadenas "válidas" es uno de los casos más comunes). Pero ahora no es necesario convertir cadenas explícitamente: la mayoría de las acciones necesarias ya están integradas en las profundidades de la biblioteca y solo están esperando una señal para actuar. 🙂 En general, la escritura funciona de forma transparente y admite casi todos los tipos de datos integrados disponibles (no se probaron frozenset, complex y bytes).

El requisito de soportar Python 2 se implementó prácticamente sin sacrificios (el abandono de escribir y algunos de los "caramelos" de las últimas versiones de Python 3), en particular, gracias a los omnipresentes seis (para resolver los problemas de uso de metaclases ).

Pero existen algunas restricciones:

  • El soporte de Python 3 significa 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, ya que es difícil encontrar una razón objetiva por la que todavía está en la 3.4);
  • En Python 2.7, la biblioteca no admite la deserialización de conjuntos literales. Descripción aquí. Pero si alguien quiere implementarlo, bienvenido :);

La biblioteca también tiene un mecanismo de excepción en caso de errores de análisis. Si ninguno de los analizadores disponibles puede reconocer la cadena, el valor sigue siendo una cadena (más bien, por razones de conveniencia y compatibilidad con la lógica habitual de cómo funcionan las variables en Bash).

biblioteca de shell de Python

Ahora les contaré sobre la segunda biblioteca (omitiré la descripción de las deficiencias de los análogos existentes; es similar a la descrita para smart-env. Análogos: aquí и aquí).

En general, la idea de implementación y sus requisitos 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 única clase que representa a Bash en el mundo de Python;
  2. Cada comando Bash se llama como una función de la clase Shell;
  3. Los parámetros para cada llamada de función luego se pasan a la llamada de comando Bash correspondiente;
  4. Cada comando se ejecuta "aquí y ahora" en el momento en que se llama, es decir. el enfoque sincrónico funciona;
  5. es posible acceder a la salida de un comando en stdout, así como a su código de retorno;
  6. Si el comando no está en el sistema, se genera una excepción.

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

Planes de desarrollo de la biblioteca.

Puede utilizar las bibliotecas ahora: ambas están publicadas 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 puede resultar difícil encontrar una variedad de características nuevas en smart-env, entonces en python-shell definitivamente hay algo más que agregar:

  • soporte para llamadas sin bloqueo;
  • posibilidad de comunicación interactiva con el equipo (trabajando con stdin);
  • agregar nuevas propiedades (por ejemplo, propiedad para recibir resultados de stderr);
  • implementación de un directorio de comandos disponibles (para usar con la función dir());
  • etcétera

referencias

  1. biblioteca de entorno inteligente: Github и PyPI
  2. Biblioteca de Python-Shell: Github и PyPI
  3. Canal de telegrama actualizaciones de la biblioteca

UPD 23.02.2020:
* Los repositorios se han movido, los enlaces correspondientes se han actualizado
* La versión python-shell==1.0.1 se está preparando para su lanzamiento el 29.02.2020/XNUMX/XNUMX. Los cambios incluyen compatibilidad con el autocompletado de comandos y el comando dir(Shell), la ejecución de comandos con un identificador de Python no válido y correcciones de errores.

Fuente: habr.com

Añadir un comentario