2010-12-22 34 views
64

Quiero ejecutar un comando en pythong, utilizando el módulo de subproceso, y almacenar la salida en una variable. Sin embargo, no quiero que la salida del comando se imprima en el terminal. Para que este código:Salida estándar de subproceso de tubería a una variable

def storels(): 
    a = subprocess.Popen("ls",shell=True) 
storels() 

me sale el listado del directorio en el terminal, en lugar de tener que almacenar en a. También lo intenté:

def storels(): 
     subprocess.Popen("ls > tmp",shell=True) 
     a = open("./tmp") 
     [Rest of Code] 
storels() 

Esto también imprime la salida de ls en mi terminal. Incluso he intentado este comando con el método os.system algo anticuado, ya que al ejecutar ls > tmp en el terminal no se imprime ls en absoluto, sino que se almacena en tmp. Sin embargo, pasa lo mismo.

Editar:

me sale el siguiente error después de seguir el consejo de marcog, pero sólo cuando se ejecuta un comando más complejo. cdrecord --help. Python escupe esto:

Traceback (most recent call last): 
    File "./install.py", line 52, in <module> 
    burntrack2("hi") 
    File "./install.py", line 46, in burntrack2 
    a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) 
    File "/usr/lib/python2.6/subprocess.py", line 633, in __init__ 
    errread, errwrite) 
    File "/usr/lib/python2.6/subprocess.py", line 1139, in _execute_child 
    raise child_exception 
OSError: [Errno 2] No such file or directory 
+2

Solo una nota, usando 'shell = true' se desaconseja en los documentos de Python. http://docs.python.org/2/library/subprocess.html#frequently-used-arguments – SamHuckaby

Respuesta

101

para obtener la salida de ls, utilice stdout=subprocess.PIPE.

>>> proc = subprocess.Popen('ls', stdout=subprocess.PIPE) 
>>> output = proc.stdout.read() 
>>> print output 
bar 
baz 
foo 

El comando cdrecord --help salidas a stderr, por lo que necesita tubería que indstead. También debe dividir el comando en una lista de tokens como he hecho a continuación, o la alternativa es pasar el argumento shell=True, pero esto dispara un shell totalmente desarrollado que puede ser peligroso si no controla el contenido de la cadena de comando.

>>> proc = subprocess.Popen(['cdrecord', '--help'], stderr=subprocess.PIPE) 
>>> output = proc.stderr.read() 
>>> print output 
Usage: wodim [options] track1...trackn 
Options: 
    -version print version information and exit 
    dev=target SCSI target to use as CD/DVD-Recorder 
    gracetime=# set the grace time before starting to write to #. 
... 

Si usted tiene un comando que da salida a stdout y stderr y desea combinar ellos, puede hacerlo mediante la canalización de stderr a stdout y luego coger la salida estándar.

subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 

Como se ha mencionado por Chris Morgan, usted debe utilizar en lugar de proc.communicate()proc.read().

>>> proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
>>> out, err = proc.communicate() 
>>> print 'stdout:', out 
stdout: 
>>> print 'stderr:', err 
stderr:Usage: wodim [options] track1...trackn 
Options: 
    -version print version information and exit 
    dev=target SCSI target to use as CD/DVD-Recorder 
    gracetime=# set the grace time before starting to write to #. 
... 
+0

Muy bien, eso funciona para 'ls', pero más tarde me encontré con un problema diferente, al tratar de ejecutar un comando diferente . Cuando trato de ejecutar "cdrecord - help" con ese método, obtengo un error de rastreo. – Insomaniacal

+0

@Insomaniacal Ver la edición – marcog

+0

¡¡¡Gracias una tonelada !! Eso lo hizo. Si no le importa que pregunte, ¿cómo diferenciaría entre usar el método stdout y este método stderr? – Insomaniacal

8

Con a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) , es necesario utilizar una lista o utilizar shell=True;

Cualquiera de estos funcionará. El primero es preferible.

a = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE) 

a = subprocess.Popen('cdrecord --help', shell=True, stdout=subprocess.PIPE) 

Además, en lugar de utilizar Popen.stdout.read/Popen.stderr.read, se debe utilizar .communicate() (consulte la documentación del subproceso de por qué).

proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
stdout, stderr = proc.communicate() 
22

Si está utilizando Python 2.7 o posterior, la forma más sencilla de hacerlo es utilizar el comando subprocess.check_output().He aquí un ejemplo:

output = subprocess.check_output('ls') 

Para redirigir también stderr puede utilizar lo siguiente:

output = subprocess.check_output('ls', stderr=subprocess.STDOUT) 



En el caso que desea pasar parámetros al comando, puede utilizar una enumerar o usar invocar un shell y usar una sola cadena.

output = subprocess.check_output(['ls', '-a']) 
output = subprocess.check_output('ls -a', shell=True) 
+0

Esto no suprime la salida, como se solicitó ("No deseo que la salida del comando se imprima en el terminal"). – Emre

+0

Esto suprime toda la salida del terminal para mí (siempre que use stderr = subprocess.STDOUT para capturar STDOUT y STDERR). ¿Tienes un comando de ejemplo donde no funciona? – amicitas

Cuestiones relacionadas