¿Cómo ejecutar un subproceso con Python, esperar a que salga y obtener el stdout completo como una cadena?

Así que noté subprocess.call mientras espera que el comando finalice antes de continuar con el script de Python, no tengo forma de obtener el stdout, excepto con subprocess.Popen . ¿Hay alguna función alternativa que espere hasta que termine? (También probé Popen.wait . Popen.wait )

NOTA: Estoy tratando de evitar la llamada a os.system

 result = subprocess.Popen([commands..., self.tmpfile.path()], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = result.communicate() print out+"HIHIHI" 

mi salida:

 HIHIHI 

NOTA: Estoy tratando de correr wine con esto.

Estoy utilizando la siguiente construcción, aunque es posible que desee evitar shell=True . Esto le da la salida y el mensaje de error para cualquier comando, y también el código de error:

 process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out, err = process.communicate() errcode = process.returncode 
 subprocess.check_output(...) 

llama al proceso, genera si su código de error es distinto de cero y, de lo contrario, devuelve su stdout. Es solo una abreviatura rápida para que no tenga que preocuparse por los PIPE y las cosas.

Si su proceso da una salida estándar enorme y no stderr, communicate() podría ser la manera incorrecta de ir debido a restricciones de memoria.

En lugar,

 process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate for line in process.stdout: do_something(line) errcode = process.returncode 

Podría ser el camino a seguir.

process.stdout es un objeto similar a un archivo que puede tratar como cualquier otro objeto similar, principalmente:

  • puedes read() de esto
  • Puedes readline() desde él y
  • puedes iterar sobre ello.

Lo último es lo que hago arriba para obtener su contenido línea por línea.

Probaría algo como:

 #!/usr/bin/python from __future__ import print_function import shlex from subprocess import Popen, PIPE def shlep(cmd): '''shlex split and popen ''' parsed_cmd = shlex.split(cmd) ## if parsed_cmd[0] not in approved_commands: ## raise ValueError, "Bad User! No output for you!" proc = Popen(parsed_command, stdout=PIPE, stderr=PIPE) out, err = proc.communicate() return (proc.returncode, out, err) 

… En otras palabras, deje que shlex.split () haga la mayor parte del trabajo. NO intentaría analizar la línea de comandos del shell, encontrar operadores de tuberías y configurar su propia canalización. Si vas a hacer eso, básicamente tendrás que escribir un analizador de syntax de shell completo y terminarás haciendo una gran cantidad de plomería.

Por supuesto, esto plantea la pregunta, ¿por qué no usar Popen con la opción shell = True (palabra clave)? Esto le permitirá pasar una cadena (sin división ni análisis) al shell y aún así recostackr los resultados para manejarlos como desee. Mi ejemplo aquí no procesará ninguna canalización, comillas invertidas, redirección del descriptor de archivos, etc. que puedan estar en el comando, todos aparecerán como argumentos literales al comando. Por lo tanto, es aún más seguro que ejecutar con shell = Verdadero … He dado un ejemplo tonto de verificar el comando contra algún tipo de diccionario o conjunto de “comando aprobado”. Tendría más sentido normalizarlo en una ruta de acceso absoluta, a menos que tenga la intención de exigir que los argumentos se normalicen antes de pasar la cadena de comando a esta función.