¿Cuál es la diferencia entre el subproceso Popen y la llamada (¿cómo puedo usarlos?)

178

Quiero llamar a un programa externo desde Python. He usado ambos Popen()y call()para hacer eso.

¿Cuál es la diferencia entre los dos?

Mi objetivo específico es ejecutar el siguiente comando desde Python. No estoy seguro de cómo funcionan las redirecciones.

./my_script.sh > output

Leí la documentación y dice que call()es una función de conveniencia o una función de acceso directo. ¿Perdemos algún poder usando en call()lugar de Popen()?

varunl
fuente
¿Qué parte de la documentación te confundió? La definición de call()parece ser muy clara. ¿Puede proporcionar una cotización o un enlace para que sepamos en qué centrarnos en una respuesta?
S.Lott

Respuestas:

265

Hay dos formas de hacer la redirección. Ambos se aplican a cualquiera subprocess.Popeno subprocess.call.

  1. Establecer el argumento de palabra clave shell = Trueo executable = /path/to/the/shelly especificar el comando del mismo modo que lo tienes ahí.

  2. Como solo está redirigiendo la salida a un archivo, establezca el argumento de la palabra clave

    stdout = an_open_writeable_file_object

    donde el objeto apunta al outputarchivo.

subprocess.Popenes más general que subprocess.call.

Popenno se bloquea, lo que le permite interactuar con el proceso mientras se está ejecutando o continuar con otras cosas en su programa Python. La llamada a Popendevuelve un Popenobjeto.

call hace bloque. Si bien admite todos los mismos argumentos que el Popenconstructor, por lo que aún puede configurar la salida del proceso, las variables ambientales, etc., su script espera a que se complete el programa y calldevuelve un código que representa el estado de salida del proceso.

returncode = call(*args, **kwargs) 

es básicamente lo mismo que llamar

returncode = Popen(*args, **kwargs).wait()

callEs solo una función de conveniencia. Su implementación en CPython está en subprocess.py :

def call(*popenargs, timeout=None, **kwargs):
    """Run command with arguments.  Wait for command to complete or
    timeout, then return the returncode attribute.

    The arguments are the same as for the Popen constructor.  Example:

    retcode = call(["ls", "-l"])
    """
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:
            p.kill()
            p.wait()
            raise

Como puede ver, es una envoltura delgada Popen.

agf
fuente
17
Básicamente, Popen y call son funciones asíncronas y síncronas, respectivamente, que se utilizan para ejecutar comandos de Linux.
user3016020
1
¿Cuál es la ventaja de usar popen? ¿No sería seguro esperar hasta que el programa llamado termine primero?
Tom
44
@Tom A menudo no. ¿Qué sucede si desea leer alguna salida, luego enviar más entradas al programa, leer más salidas que resultan de esa entrada, repetir?
AGF
@ user3016020 ¿Supongo que esto también se aplica a los comandos de Windows? ¿Correcto?
domih
7

La otra respuesta es muy completa, pero aquí hay una regla general:

  • call está bloqueando:

    call('notepad.exe')
    print('hello')  # only executed when notepad is closed
  • Popen no es bloqueante:

    Popen('notepad.exe')
    print('hello')  # immediately executed
Basj
fuente