2012-06-29 21 views
194

estoy usando eSpeak en Ubuntu y tener un script en Python 2.7 que las impresiones y habla un mensaje:Cómo ocultar salida del subproceso en Python 2.7

import subprocess 
text = 'Hello World.' 
print text 
subprocess.call(['espeak', text]) 

eSpeak produce los sonidos deseados, pero estorba la cáscara con algunos errores (ALSA lib ..., no socket connect) por lo que no puedo leer fácilmente lo que se imprimió antes. El código de salida es 0.

Desafortunadamente no hay una opción documentada para desactivar su verbosidad, por lo que estoy buscando una forma de silenciarlo visualmente y mantener el shell abierto limpio para una mayor interacción.

¿Cómo puedo hacer esto?

+0

¿No podría simplemente llamar con os.system entonces? no es ideal, pero no debe imprimir. No creo –

+0

@JoranBeasley: os.system() se imprimirá en la consola a menos que redirija el comando de shell – jdi

+0

no, os.system ('espeak' + text) reproduce este comportamiento. – ferkulat

Respuesta

292

redirigir la salida a Devnull:

import os 
import subprocess 

FNULL = open(os.devnull, 'w') 
retcode = subprocess.call(['echo', 'foo'], stdout=FNULL, stderr=subprocess.STDOUT) 

En efecto, es lo mismo que ejecutar este comando shell:

retcode = os.system("echo 'foo' &> /dev/null") 
+40

selecciones micropulidas: puede usar 'os.devnull' si' subprocess.DEVNULL' no está disponible (<3.3), use 'check_call()' en vez de 'call()' si no verifica su código devuelto, abrir archivos en modo binario para 'stdin/stdout/stderr', el uso de' os.system() 'debe ser desaconsejado,' &> 'no funciona para' sh' en Ubuntu y '' exp/null 2 > & 1' podría ser utilizado. – jfs

+0

@ J.F.Sebastian: Gracias por las sugerencias. De hecho, quise usar 'os.devnull' pero accidentalmente lo escribí. Además, me estoy quedando con el uso de OPs de 'call' ya que no están captando la posible excepción que' check_call' plantearía. Y para el redireccionamiento 'os.system', era más simplemente una ilustración de lo que está haciendo el uso efectivo del enfoque de subproceso. No realmente como una segunda sugerencia. – jdi

+10

¿No necesita cerrar el FNULL que ha abierto? – Val

64

Aquí hay una versión más portátil (sólo por diversión, no es necesario su caso):

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
from subprocess import Popen, PIPE, STDOUT 

try: 
    from subprocess import DEVNULL # py3k 
except ImportError: 
    import os 
    DEVNULL = open(os.devnull, 'wb') 

text = u"René Descartes" 
p = Popen(['espeak', '-b', '1'], stdin=PIPE, stdout=DEVNULL, stderr=STDOUT) 
p.communicate(text.encode('utf-8')) 
assert p.returncode == 0 # use appropriate for your program error handling here 
+2

Tenga en cuenta que esto produce un 'DEVNULL' que no es completamente general, como el proporcionado por' subproceso'; ya que está abierto 'wb' no se puede usar para' stdin'. – Reid

+0

@Reid: puede usar el modo ''r + b'' si lo necesita en su lugar. – jfs

-5

¿Por qué no utilizar commands.getoutput() en su lugar?

import commands 

text = "Mario Balotelli" 
output = 'espeak "%s"' % text 
print text 
a = commands.getoutput(output) 
+0

a) no descarta la entrada, la acumula innecesariamente en la memoria b) se rompe si 'text' tiene comillas en ella, o utiliza una codificación de caracteres diferente, o demasiado grande para una línea de comando c) solo es Unix (en Python 2) – jfs

18

Uso subprocess.check_output (nuevo en Python 2.7). Suprimirá stdout y generará una excepción si el comando falla. (En realidad, devuelve el contenido de la salida estándar, por lo que puede usar esa tarde en su programa si lo desea.) Ejemplo:

import subprocess 
try: 
    subprocess.check_output(['espeak', text]) 
except subprocess.CalledProcessError: 
    # Do something 

También puede suprimir stderr con:

subprocess.check_output(["espeak", text], stderr=subprocess.STDOUT) 

Para más temprano que 2,7 , utiliza

import os 
import subprocess 
with open(os.devnull, 'w') as FNULL: 
    try: 
     subprocess._check_call(['espeak', text], stdout=FNULL) 
    except subprocess.CalledProcessError: 
     # Do something 

Aquí, puede suprimir stderr con

 subprocess._check_call(['espeak', text], stdout=FNULL, stderr=FNULL) 
+0

Más precisamente, devuelve el stdout. Lo cual es genial ya que podría querer usarlo además de poder ignorarlo. –

+0

Sin embargo, no enmascara errores estándar. – SmallChess

+0

Creo que esto es más sencillo. @StudentT Creo que debes manejar los errores con CalledProcessError. 'excepto subprocess.CalledProcessError como e' y luego use' e.code' o 'e.output' –

0

si está utilizando el módulo de subproceso en Windows (no específico de esta pregunta pero coincide con el título) con python 2.7x y SÓLO es el error que desea suprimir (específico de esta pregunta), puede hacer algo como esto:

output = subprocess.check_output(["arp", "-a", "-N", "127.0.0.2"], stderr=subprocess.STDOUT)

usted debe ser capaz de probar utilizando el código anterior en su sistema, pero si 127.0.0.2 pasa a existir en su tabla ARP sólo se puede recoger una ip que no tiene una tarjeta de red asociado con eso.

+1

Eso no suprime los errores. Redirecciona stderr a stdout, por lo que 'output' ha generado resultados y errores, lo que probablemente no es lo que se desea. –

Cuestiones relacionadas