2011-12-16 13 views
35

¿Existe una variante de subprocess.call que pueda ejecutar el comando sin imprimir a la salida estándar, o una forma de bloquear su salida estándar?¿Hay una versión silenciosa de subprocess.call?

+0

Estrechamente relacionado http://stackoverflow.com/questions/5495078/how-do-you-discard-subprocess-output-in-python, en particular debido llamada utiliza Popen. –

+0

relacionado: [Cómo ocultar la salida del subproceso en Python 2.7] (http://stackoverflow.com/q/11269575/4279) – jfs

Respuesta

40

Sí. Redirigir su stdout al /dev/null.

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb')) 
+1

'Popen' no es una variante de' call'. Es una función completamente diferente. – jwg

+1

Tienes razón. Sin embargo, Popen y call tienen argumentos muy similares, por lo que estas soluciones funcionan para ambos. He enviado una edición. – jhrf

+4

Tenga en cuenta que desde Python ver. 3.3 existe en realidad un 'subproceso.DEVNULL', que se puede usar en lugar de' open (os.devnull, 'wb') '. – EquipDev

19

A menudo ese tipo de chatter está en stderr, por lo que también querrá silenciarlo. Aquí está mi ejemplo:

from subprocess import call, DEVNULL 
return_code = call(args, stderr=DEVNULL, stdout=DEVNULL) 

Nota:subprocess.DEVNULL está disponible desde Python 3.3. Si usted todavía está en Python 2:

import os 

with open(os.devnull, 'w') as shutup: 
    return_code = call(args, stdout=shutup, stderr=shutup) 
+0

notando que no se necesita ninguna respuesta sobre el uso de 'startupinfo' como se muestra aquí: http://code.activestate.com/recipes/409002-launching-a-subprocess-without-a-console-window/ para evitar el parpadeo de la ventana cuando se ejecuta Python fuera de una consola –

+0

python 3 ahora tiene 'subproceso.DEVNULL' (pero tu respuesta es 7 años) –

+0

@ Jean-FrançoisFabre Esto ya fue mencionado en un comentario sobre la respuesta aceptada. De todos modos, lo he editado ahora, gracias por la sugerencia. – wim

10

subprocess.call aceptan también redirecciones de la entrada estándar/stdout/stderr:

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb')) 
+2

[Los documentos] (http://docs.python.org/2/library/subprocess.html#subprocess.call) dicen específicamente "No use stdout = PIPE o stderr = PIPE con esta función". – mpen

+6

open() no devuelve un PIPE, el PIPE significa 'subprocess.PIPE' que se puede leer desde el otro extremo del programa. Una apertura a 'os.devnull' no causará problemas porque no hay fondo en este archivo de agujero negro, el búfer nunca se va a llenar. – BOYPT

+0

Ah. Eso tiene sentido. ¡Gracias! No quería tener que usar 'Popen' ya que devuelve un proceso en lugar de un código de estado. – mpen

1

Esta es una receta que utilizo mucho: llamar subprocess y recoger la salida, y cuando el comando logra descartar la salida, pero cuando falla imprime la salida.

import subprocess as sp 
import sys 

if "print" in __builtins__.__dict__: 
    prn = __builtins__.__dict__["print"] 
else: 
    def prn(*args, **kwargs): 
     """ 
     prn(value, ..., sep=' ', end='\\n', file=sys.stdout) 
     Works just like the print function in Python 3.x but can be used in 2.x. 

     Prints the values to a stream, or to sys.stdout by default. 
     Optional keyword arguments: 
     file: a file-like object (stream); defaults to the current sys.stdout. 
     sep: string inserted between values, default a space. 
     end: string appended after the last value, default a newline. 
     """ 
     sep = kwargs.get("sep", ' ') 
     end = kwargs.get("end", '\n') 
     file = kwargs.get("file", sys.stdout) 

     s = sep.join(str(x) for x in args) + end 
     file.write(s) 


def rc_run_cmd_basic(lst_cmd, verbose=False, silent=False): 
    if silent and verbose: 
     raise ValueError("cannot specify both verbose and silent as true") 

    p = sp.Popen(lst_cmd, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE) 
    tup_output = p.communicate() 

    s_cmd = ' '.join(lst_cmd) 
    if verbose: 
     prn() 
     prn("command: '%s'\n" % s_cmd) 

     if 0 != p.returncode: 
      prn() 
      prn("Command failed with code %d:" % p.returncode) 
     else: 
      prn("Command succeeded! code %d" % p.returncode) 
    if verbose: 
     prn("Output for: " + s_cmd) 
     prn(tup_output[0]) 
     prn() 
    if not silent and 0 != p.returncode: 
     prn("Error output for: " + s_cmd) 
     prn(tup_output[1]) 
     prn() 

    return p.returncode 
0

Utilizo subprocess.check_output en tales casos y elimino el valor de retorno. Es posible que desee agregar un comentario a su código que indique por qué está utilizando check_output en lugar de check_call. check_output también es más agradable cuando ocurre una falla y le interesa el resultado del error. Ejemplo de código a continuación. La salida se ve solo cuando descomenta la línea de impresión. Si el comando falla, se lanza una excepción.

import subprocess 
ret = subprocess.check_output(["cat", "/tmp/1"]) 
#print ret 
+0

¿De qué manera la caída del valor de retorno impide que la salida sea stdout? – Emre

+0

subprocess.check_output se supone que captura el resultado y lo devuelve. ¿Ves un comportamiento diferente? –

+0

Capturar e ignorar funciona, pero desperdicia memoria en el valor capturado que luego nunca se usa. Descartar la salida correctamente es más robusto. – tripleee

Cuestiones relacionadas