Necesito ejecutar un comando de shell de forma asincrónica desde un script de Python. Con esto quiero decir que quiero que mi script de Python continúe ejecutándose mientras el comando externo se apaga y hace lo que sea necesario.
Leí esta publicación:
Luego me fui e hice algunas pruebas, y parece os.system()
que hará el trabajo siempre que use &
al final del comando para no tener que esperar a que regrese. Lo que me pregunto es si esta es la forma correcta de lograr tal cosa. Lo intenté commands.call()
pero no me funcionará porque bloquea el comando externo.
Por favor, avíseme si os.system()
es aconsejable usarlo para esto o si debería probar alguna otra ruta.
fuente
Si desea ejecutar muchos procesos en paralelo y luego manejarlos cuando produzcan resultados, puede usar el sondeo como en el siguiente:
El flujo de control allí es un poco complicado porque estoy tratando de hacerlo pequeño, puede refactorizar a su gusto. :-)
Esto tiene la ventaja de atender primero las solicitudes de finalización anticipada. Si llama
communicate
al primer proceso en ejecución y resulta que se ejecuta por más tiempo, los otros procesos en ejecución habrán estado inactivos cuando podría haber estado manejando sus resultados.fuente
os.waitpid
directamente lo que permite verificar si algún proceso hijo ha cambiado su estado.['/usr/bin/my_cmd', '-i', path]
lugar de['/usr/bin/my_cmd', '-i %s' % path]
Lo que me pregunto es si este [os.system ()] es la forma correcta de lograr tal cosa.
No.
os.system()
no es la forma correcta. Por eso todo el mundo dice que lo usesubprocess
.Para obtener más información, lea http://docs.python.org/library/os.html#os.system
fuente
He tenido mucho éxito con el módulo asyncproc , que se ocupa muy bien de la salida de los procesos. Por ejemplo:
fuente
Usar pexpect con readlines que no bloquean es otra forma de hacer esto. Pexpect resuelve los problemas de interbloqueo, le permite ejecutar fácilmente los procesos en segundo plano y ofrece formas sencillas de tener devoluciones de llamada cuando su proceso escupe cadenas predefinidas y, en general, hace que la interacción con el proceso sea mucho más fácil.
fuente
Teniendo en cuenta "No tengo que esperar a que vuelva", una de las soluciones más fáciles será la siguiente:
Pero ... Por lo que leí, esta no es "la forma correcta de lograr tal cosa" debido a los riesgos de seguridad creados por la
subprocess.CREATE_NEW_CONSOLE
bandera.Las cosas clave que suceden aquí es el uso de
subprocess.CREATE_NEW_CONSOLE
para crear una nueva consola y.pid
(devuelve el ID del proceso para que pueda verificar el programa más adelante si lo desea) para no esperar a que el programa termine su trabajo.fuente
Tengo el mismo problema al intentar conectarme a un terminal 3270 utilizando el software de scripting s3270 en Python. Ahora estoy resolviendo el problema con una subclase de proceso que encontré aquí:
http://code.activestate.com/recipes/440554/
Y aquí está la muestra tomada del archivo:
fuente
La respuesta aceptada es muy antigua.
Encontré una mejor respuesta moderna aquí:
https://kevinmccarthy.org/2016/07/25/streaming-subprocess-stdin-and-stdout-with-asyncio-in-python/
e hizo algunos cambios:
Es poco probable que los comandos de ejemplo funcionen perfectamente en su sistema y no maneja errores extraños, pero este código demuestra una forma de ejecutar múltiples subprocesos usando asyncio y transmitir la salida.
fuente
wait()
directamente está obsoletoAquí hay varias respuestas, pero ninguna de ellas cumplió con mis requisitos a continuación:
No quiero esperar a que termine el comando o contaminar mi terminal con salidas de subproceso.
Quiero ejecutar un script bash con redireccionamientos.
Quiero admitir tuberías dentro de mi script bash (por ejemplo
find ... | tar ...
).La única combinación que satisface los requisitos anteriores es:
fuente
Esto está cubierto por Ejemplos de subprocesos de Python 3 en "Esperar a que el comando termine de forma asincrónica":
El proceso comenzará a ejecutarse tan pronto como se
await asyncio.create_subprocess_exec(...)
haya completado. Si no ha terminado para cuando llameawait proc.communicate()
, esperará allí para darle su estado de salida. Si ha terminado,proc.communicate()
volverá inmediatamente.La esencia aquí es similar a la respuesta de Terrel pero creo que la respuesta de Terrels parece complicar demasiado las cosas.
Consulte
asyncio.create_subprocess_exec
para obtener más información.fuente