¿Cómo canalizo una llamada de subproceso a un archivo de texto?

97
subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml",  "/tmp/video_xml"])

Ahora mismo tengo un script que ejecuto. Cuando lo ejecuto y llega a esta línea, comienza a imprimir cosas porque run.sh tiene impresiones.

¿Cómo canalizo esto también a un archivo de texto? (Y también imprimir, si es posible)

TIMEX
fuente

Respuestas:

179

Si desea escribir la salida en un archivo, puede usar el argumento stdout de subprocess.call.

Toma None, subprocess.PIPEun objeto de archivo o un descriptor de archivo. El primero es el predeterminado, stdout se hereda del padre (su script). El segundo le permite pasar de un comando / proceso a otro. El tercero y el cuarto son los que desea, tener la salida escrita en un archivo.

Debe abrir un archivo con algo como openy pasar el objeto o el descriptor de archivo entero a call:

f = open("blah.txt", "w")
subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml",  "/tmp/video_xml"], stdout=f)

Supongo que cualquier objeto válido similar a un archivo funcionaría, como un socket (jadeo :)), pero nunca lo he intentado.

Como menciona marcog en los comentarios, es posible que también desee redirigir stderr, puede redirigir esto a la misma ubicación que stdout con stderr=subprocess.STDOUT. Cualquiera de los valores mencionados anteriormente también funciona, puede redirigir a diferentes lugares.

Skurmedel
fuente
6
¿Por qué no funciona subprocess.call (["echo", "1", ">>", "t.txt"])?
StackOverflowOfficial
7
@Goldname necesita un shell para hacer la redirección, entonces: subprocess.call(["echo", "1", ">>", "t.txt"], shell=True)debería funcionar.
Wes Mason
@WesMason Gracias, pero pensé que subprocess.call funcionaba de una manera que era básicamente como copiar y pegar en el shell.
StackOverflowOfficial
2
@Goldname nah, todo en el subproceso se basa en la clase Popen subyacente, que abre un proceso, shell = True forzará la ejecución del proceso en el shell predeterminado del sistema (por ejemplo, / bin / sh en sistemas POSIX, que generalmente es bash o dash ), es más seguro de esa manera, ya que no está abierto a todas las funciones adicionales proporcionadas por el shell (un lenguaje de programación completo en sí mismo, con sus propios exploits si pasa datos proporcionados por el usuario). También eche un vistazo shlex.quotesi está pasando datos posiblemente sucios a una subcapa.
Wes Mason
4
¿También deberíamos cerrar el archivo después de que hayamos terminado? esto cerrará el archivo después de que terminemos: with open("blah.txt","w") as f: subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml", "/tmp/video_xml"], stdout=f) @Skurmedel
Alper
19

Las opciones para popense pueden utilizar encall

args, 
bufsize=0, 
executable=None, 
stdin=None, 
stdout=None, 
stderr=None, 
preexec_fn=None, 
close_fds=False, 
shell=False, 
cwd=None, 
env=None, 
universal_newlines=False, 
startupinfo=None, 
creationflags=0

Entonces...

subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml",  "/tmp/video_xml"], stdout=myoutput)

Entonces puede hacer lo que quiera con myoutput(que debería ser un archivo por cierto).

Además, puede hacer algo más parecido a una salida canalizada como esta.

dmesg | grep hda

sería:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

Hay mucha información interesante y útil en la página del manual de Python .

ocodo
fuente
-2

También puede simplemente llamar al script desde la terminal, enviando todo a un archivo, si eso ayuda. De esta manera:

$ /path/to/the/script.py > output.txt

Esto sobrescribirá el archivo. Puede usar >>para agregarlo.

Si también desea que se registren errores en el archivo, utilice &>>o &>.

Danilo Martins
fuente