Comando de Python popen. Espere hasta que termine el comando

79

Tengo un script en el que lanzo con popen un comando de shell. El problema es que la secuencia de comandos no espera hasta que finalice el comando popen y continúa inmediatamente.

om_points = os.popen(command, "w")
.....

¿Cómo puedo decirle a mi secuencia de comandos de Python que espere hasta que el comando de shell haya finalizado?

michele
fuente

Respuestas:

112

Dependiendo de cómo quiera trabajar su script, tiene dos opciones. Si desea que los comandos se bloqueen y no hagan nada mientras se ejecuta, puede usar subprocess.call.

#start and block until done
subprocess.call([data["om_points"], ">", diz['d']+"/points.xml"])

Si desea hacer cosas mientras se ejecuta o alimentar cosas stdin, puede usarlo communicatedespués de la popenllamada.

#start and process things, then wait
p = subprocess.Popen([data["om_points"], ">", diz['d']+"/points.xml"])
print "Happens while running"
p.communicate() #now wait plus that you can send commands to process

Como se indica en la documentación, se waitpuede interbloquear, por lo que es recomendable comunicarse.

profano
fuente
Consulte los documentos en subprocess.call
thornomad
Si bien el subproceso se prefiere en muchas respuestas, no puede manejar muy bien el espacio y la cuota dentro del comando. La respuesta anterior no resuelve directamente la pregunta de os.popen.
Chang
el subproceso puede ser hasta 2 veces
MonsieurBeilto
subprocess.run()se agregó en Python 3.5 y es "El enfoque recomendado para invocar subprocesos"
LoMaPh
29

Puede utilizar subprocesspara lograr esto.

import subprocess

#This command could have multiple commands separated by a new line \n
some_command = "export PATH=$PATH://server.sample.mo/app/bin \n customupload abc.txt"

p = subprocess.Popen(some_command, stdout=subprocess.PIPE, shell=True)

(output, err) = p.communicate()  

#This makes the wait possible
p_status = p.wait()

#This will give you the output of the command being executed
print "Command output: " + output
Piedra de toque
fuente
El subproceso puede ser hasta 2 veces más lento que el sistema operativo
MonsieurBeilto
12

Obligar popena no continuar hasta que se lea toda la salida haciendo:

os.popen(command).read()
Alberto
fuente
2
No soy un experto en Python, pero esta parece ser la solución más simple que hace la menor cantidad de modificaciones al código original. ¿Alguna razón por la que esta no sería una buena solución?
jdmcnair
7

Deja que el comando que intentas pasar sea

os.system('x')

luego lo convertiste en una declaración

t = os.system('x')

ahora, Python estará esperando el resultado de la línea de comandos para poder asignarlo a la variable t.

Chidhambararajan NRM
fuente
4

Lo que buscas es el waitmétodo.

Olivier Verdier
fuente
Pero si escribo: om_points = os.popen (data ["om_points"] + ">" + diz ['d'] + "/ points.xml", "w"). Wait () Recibo este error: Traceback (última llamada más reciente): Archivo "./model_job.py", línea 77, en <module> om_points = os.popen (data ["om_points"] + ">" + diz ['d'] + "/ points .xml "," w "). wait () AttributeError: el objeto 'file' no tiene atributo 'wait' ¿Cuál es el problema? Gracias de nuevo.
michele
12
No hizo clic en el enlace que proporcioné. waites un método de la subprocessclase.
Olivier Verdier
1
esperar puede interbloqueo si el proceso escribe en stdout y nadie lo lee
ansgri
El subproceso puede ser hasta 2 veces más lento que el sistema operativo
MonsieurBeilto
2

wait () funciona bien para mí. Los subprocesos p1, p2 y p3 se ejecutan al mismo tiempo. Por lo tanto, todos los procesos se realizan después de 3 segundos.

import subprocess

processes = []

p1 = subprocess.Popen("sleep 3", stdout=subprocess.PIPE, shell=True)
p2 = subprocess.Popen("sleep 3", stdout=subprocess.PIPE, shell=True)
p3 = subprocess.Popen("sleep 3", stdout=subprocess.PIPE, shell=True)

processes.append(p1)
processes.append(p2)
processes.append(p3)

for p in processes:
    if p.wait() != 0:
        print("There was an error")

print("all processed finished")
simibac
fuente
El subproceso puede ser hasta 2 veces más lento que el sistema operativo
MonsieurBeilto
0

Creo que process.communicate () sería adecuado para una salida de tamaño pequeño. Para una producción mayor, no sería el mejor enfoque.

Barsha Lamichhane
fuente