Si utiliza Linux, entonces seguro que le encantan los comandos shell.
Y si está trabajando con Python, entonces es posible que haya intentado automatizar cosas. Es una forma de ahorrar tiempo. También es posible que tenga algunos scripts en bash para automatizar cosas.
Python es más práctico para escribir scripts que bash. Y la gestión de los scripts Python es más fácil que la de los scripts bash. Le resultará difícil mantener los scripts bash una vez que crezcan.
¿Pero qué pasa si ya tiene scripts bash que quiere ejecutar usando Python?
¿Hay alguna forma de ejecutar los comandos y scripts bash en Python?
Sí, Python tiene un módulo incorporado llamado subproceso que se utiliza para ejecutar los comandos y scripts dentro de los scripts de Python. Veamos cómo ejecutar comandos y scripts bash en scripts Python en detalle.
Ejecutando Comandos Bash
Como ya habrá visto el módulo subproceso se utiliza para ejecutar los comandos y scripts bash. Proporciona diferentes métodos y clases para lo mismo.
Hay principalmente un método y una clase que conocer del módulo subproceso. Ellos son ejecute y Popen. Estos dos nos ayudan a ejecutar los comandos bash en scripts Python. Veámoslos uno a uno.
subproceso.run()
El método subprocess
.run() tomará una lista de cadenas como argumento posicional. Esto es obligatorio ya que tiene el comando bash y argumentos para ello. El primer elemento de la lista es el nombre del comando y los elementos restantes son los argumentos del comando.
Veamos un ejemplo rápido.
import subprocess
subprocess.run(["ls"])
La secuencia de comandos anterior lista todos los elementos del directorio de trabajo actual mientras se encuentra la secuencia de comandos. No hay argumentos para el comando en el script anterior. Sólo hemos dado el comando bash. Podemos proporcionar argumentos adicionales al comando ls
como -l
, -a
, -la
etc.
Veamos un ejemplo rápido con argumentos del comando.
import subprocess
subprocess.run(["ls", "-la"])
El comando anterior muestra todos los archivos, incluidos los ocultos, junto con los permisos. Hemos proporcionado el argumento la que muestra la
información extra de los archivos y directorios y los archivos ocultos.
Es posible que cometamos algunos errores al escribir los comandos. Los errores se levantarán de acuerdo a los errores. ¿Y si queremos capturarlos y utilizarlos más tarde? Sí, podemos hacerlo utilizando el argumento clave stderr.
Veamos un ejemplo.
import subprocess
result = subprocess.run(["cat", "sample.txt"], stderr=subprocess.PIPE, text=True)
print(result.stderr)
Asegúrese de que no tiene el archivo con el nombre sample . txt en el directorio de trabajo. El valor de la palabra clave argumento stderr es TUBO que ayuda a devolver el error en un objeto. Podremos acceder a él más tarde con el mismo nombre. Y el argumento de palabra clave texto ayuda a decir que la salida debe ser una cadena.
Del mismo modo, podemos capturar la salida del comando utilizando el argumento de palabra clave stdout .
import subprocess
result = subprocess.run(["echo", "¡Hola, Mundo!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
print(result.stdout)
subproceso.run() - entrada
Puede dar entrada a los comandos utilizando el argumento de la palabra clave entrada . Nosotros daremos entradas en un formato de cadena. Por lo tanto, necesitamos establecer la palabra clave argumento texto a True
. Por defecto, lo toma en bytes.
Veamos un ejemplo.
import subproceso
subprocess.run(["python3", "add.py"], text=True, input="2 3")
En el programa anterior, el script Python add. py tomará dos números como entrada. Hemos dado la entrada al script de Python utilizando el argumento de la palabra clave entrada .
subproceso.Popen()
La clase subproceso .Popen() es más avanzado que el método subproceso.ejecutar(). Nos da más opciones para ejecutar los comandos. Crearemos una instancia del subproceso.Popen( ) y la utilizaremos para varias cosas como conocer el estado de la ejecución del comando, obtener salida, dar entrada, etc..,
Hay varios métodos de la clase subprocess.Popen() que necesitamos conocer. Veámoslos uno a uno junto con los ejemplos de código.
espere
Se utiliza para esperar hasta la finalización de la ejecución del comando. Las siguientes líneas del script Python no se ejecutarán hasta la finalización del comando anterior que se escriba después del método wait
. Veamos el ejemplo.
import subproceso
proceso = subproceso.Popen(["ls", "-la"])
print("¡Completado!")
Ejecute el código anterior y observe la salida. Verá que el mensaje ¡Completado! ! se imprime antes de la ejecución del comando. Podemos evitarlo utilizando el método wait
. Esperemos hasta la finalización del comando.
import subprocess
process = subprocess.Popen(["ls", "-la"])
process.wait()
print("¡Completado!")
Si ve la salida del código anterior, se dará cuenta de que wait
funciona realmente. La sentencia print se ejecuta tras la finalización de la ejecución del comando.
comunicar
El método communicate
se utiliza para obtener la salida, el error y dar entrada al comando. Devuelve una tupla que contiene la salida y el error respectivamente. Veamos un ejemplo.
import subproceso
proceso = subproceso.Popen(["echo", "¡Hola, mundo!"], stdout=subproceso.PIPE, stderr=subproceso.PIPE, text=True)
resultado = proceso.communicate()
print(resultado)
subproceso.Popen() - entrada
No podemos pasar la entrada a la clase Popen
directamente. Necesitamos utilizar la palabra clave argumento llamado stdin para dar la entrada al comando. La instancia de la clase Popen
nos proporcionará el objeto stdin
. Tiene un método llamado write
que se utiliza para dar la entrada al comando.
Como discutimos anteriormente, tomará las entradas como objetos tipo bytes por defecto. Por lo tanto, no olvide establecer la palabra clave argumento texto a True
mientras crea la instancia de Popen
.
Veamos un ejemplo.
import subprocess
process = subprocess.Popen(["python3", "add.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
process.stdin.write("2 3")
process.stdin.close()
print(process.stdout.read())
sondear
El método poll
se utiliza para comprobar si la ejecución del comando se ha completado o no. Este método devolverá None
si el comando aún se está ejecutando. Veamos un ejemplo.
import subprocess
process = subprocess.Popen(['ping', '-c 5', 'geekflare.com'], stdout=subprocess.PIPE, text=True)
while True:
output = process.stdout.readline()
if output:
print(output.strip())
result = process.poll()
if result is not None:
break
En el código anterior, hemos utilizado el comando ping
con 5 peticiones. Hay un bucle infinito que itera hasta la finalización de la ejecución del comando. Hemos utilizado el método poll
para comprobar el estado de la ejecución del comando. Si el método poll
devuelve un código distinto de None
Entonces la ejecución se completa. Y el bucle infinito se rompe.
Ejecución de scripts Bash
Hemos visto dos formas de ejecutar los comandos. Ahora, veamos cómo ejecutar los scripts bash en scripts Python.
El subproceso tiene un método llamado llamada. Este método se utiliza para ejecutar los scripts bash. El método devuelve el código de salida del script bash. El código de salida por defecto para los scripts bash es 0. Veamos un ejemplo.
Cree un script bash con el nombre practice.sh de la siguiente manera.
#!/bin/bash
echo "¡Hola, mundo!"
exit 1
Ahora, escriba un script Python que ejecute el script bash anterior.
import subproceso
codigo_salida = subproceso.call('./práctica.sh')
print(codigo_salida)
Obtendrá la siguiente salida una vez que ejecute el script Python anterior.
Hola, mundo!
1
Conclusión
Hemos visto cómo ejecutar comandos y scripts bash en Python. Puede utilizarlos para automatizar cosas de manera más eficiente.
Feliz Codificación 👨💻