2011-02-11 21 views
64

Lo que hago en la línea de comandos:Python: ¿Cómo redirigir la salida con subproceso?

cat file1 file2 file3 > myfile 

Lo que yo quiero hacer con Python:

import subprocess, shlex 
my_cmd = 'cat file1 file2 file3 > myfile' 
args = shlex.split(my_cmd) 
subprocess.call(args) # spits the output in the window i call my python program 
+0

Ejecutar dicho comando en subproceso no le daría ningún resultado. ¿Puede ser que desee ejecutarlo sin _> myfile_ redirigir el resultado de _cat file1 file2 file3_ into python? – PoltoS

+0

@PoltoS Quiero unir algunos archivos y luego procesar el archivo resultante. Pensé que usar gato era la alternativa más fácil. ¿Hay una mejor/pitónica forma de hacerlo? – catatemypythoncode

+0

'solución basada en' os.sendfile() 'es posible, vea [Reproducir el comando unix cat en python] (http://stackoverflow.com/q/11532980/4279) – jfs

Respuesta

23

ACTUALIZACIÓN: os.system no es recomendable, aunque todavía está disponible en Python 3.


uso os.system:

os.system(my_cmd) 

Si realmente desea utilizar subproceso, aquí está la solución (en su mayoría levantado de la documentación para el subproceso):

p = subprocess.Popen(my_cmd, shell=True) 
os.waitpid(p.pid, 0) 

otoh, puede evitar las llamadas al sistema en su totalidad:

import shutil 

with open('myfile', 'w') as outfile: 
    for infile in ('file1', 'file2', 'file3'): 
     shutil.copyfileobj(open(infile), outfile) 
+1

Funciona, pero déjame preguntarte entonces: ¿Cuál es el punto de la biblioteca de subprocesos si os.system ya hace el trabajo? Me da la sensación de que debería haber estado utilizando un subproceso en su lugar, ya que es una biblioteca dedicada a esta tarea, aunque como estoy haciendo esto solo para mí, estaré bien usando os.system esta vez. – catatemypythoncode

+0

La biblioteca de subprocesos es mucho más flexible que 'os.system', y puede modelar' os.system' con precisión, pero también es más complejo trabajar con ella. –

+11

'os.system' vino antes de' subprocess'. El primero es una API heredada que este último intenta reemplazar. – Santa

4

@ PoltoS Quiero unir algunos archivos y luego procesar el archivo resultante. Pensé que usar gato era la alternativa más fácil. ¿Hay una mejor/pitónica forma de hacerlo?

Por supuesto:

with open('myfile', 'w') as outfile: 
    for infilename in ['file1', 'file2', 'file3']: 
     with open(infilename) as infile: 
      outfile.write(infile.read()) 
165

Para responder a su pregunta original, para redirigir la salida, sólo tiene que pasar un identificador de archivo abierto para la stdout argumento para subprocess.call:

# Use a list of args instead of a string 
input_files = ['file1', 'file2', 'file3'] 
my_cmd = ['cat'] + input_files 
with open('myfile', "w") as outfile: 
    subprocess.call(my_cmd, stdout=outfile) 

Pero, como otros tienen señalado, el uso de un comando externo como cat para este propósito es completamente extraño.

+2

Esta debería ser la respuesta para la cuestión general de la tubería cuando se utiliza el shell de Python –

+25

Esta es la respuesta correcta, no la que se marcó como correcta. –

+0

Esta es la respuesta correcta, el mejor enfoque. –

0

Un caso interesante sería actualizar un archivo al agregarle un archivo similar. Entonces uno no tendría que crear un nuevo archivo en el proceso. Es particularmente útil en el caso donde se necesita agregar un archivo grande. Aquí hay una posibilidad de usar la línea de comando teminal directamente desde python.

import subprocess32 as sub 

with open("A.csv","a") as f: 
    f.flush() 
    sub.Popen(["cat","temp.csv"],stdout=f) 
0
size = 'ffprobe -v error -show_entries format=size -of default=noprint_wrappers=1:nokey=1 dump.mp4 > file' 
proc = subprocess.Popen(shlex.split(size), shell=True) 
time.sleep(1) 
proc.terminate() #proc.kill() modify it by a suggestion 
size = "" 
with open('file', 'r') as infile: 
    for line in infile.readlines(): 
     size += line.strip() 

print(size) 
os.remove('file') 

Cuando se utiliza subproceso, el proceso debe ser killed.This es un example.If no se mata el proceso, archivo estará vacía y se puede leer nothing.It puede ejecutarse en Windows. No me puedo asegurar de que pueda ejecutarse en Unix.

+0

Es un mal ejemplo de código (no funcionará en Unix; muestra malas prácticas 'para la línea en .readlines():', 's + =') y 'proc.kill()' puede llevar a la pérdida de información en general (no permite que el subproceso finalice correctamente (en Unix) - se pierde el contenido no eliminado). De todos modos, la nota sobre el almacenamiento en búfer es más apropiada como comentario. – jfs

+0

Lo ejecuto en Windows está bien (Porque kill es igual a terminar en Windows). En Unix puede ser que deberías usar proc.terminate(). @ J.F. Sebastian No tengo el Sistema Unix en mi computadora. – wyx

+0

Si está en Windows, suelte 'shlex.split()', suelte 'shell = True', coloque'> file', coloque 'open()', etc. y use 'stdout = PIPE',' Timer (1, proc.terminate) .start() '; 'output = proc.communicate() [0]' en su lugar. Aquí está [ejemplo completo] (http://stackoverflow.com/a/27995163/4279). Más soluciones: [¿Dejar de leer el resultado del proceso en Python sin bloqueo?] (Http://stackoverflow.com/q/4417962/4279) Nota: no hay ningún requisito en la pregunta de que deba finalizar el proceso hijo manualmente: usted podría abordar otros problemas, por ejemplo, un proceso puede comportarse de manera diferente si su stdout es un tty pero está fuera de tema. – jfs

Cuestiones relacionadas