2011-12-16 15 views
35

Esiste una variante di subprocess.call che può eseguire il comando senza la stampa dello standard o un modo per bloccare i messaggi standard?Esiste una versione silenziosa di subprocess.call?

+0

strettamente legato http://stackoverflow.com/questions/5495078/how-do-you-discard-subprocess-output-in-python, in particolare a causa delle chiamate utilizza Popen. –

+0

correlati: [Come nascondere l'output del sottoprocesso in Python 2.7] (http://stackoverflow.com/q/11269575/4279) – jfs

risposta

40

Sì. Reindirizzare il suo stdout a /dev/null.

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

'Popen' non è una variante di' call'. È una funzione completamente diversa. – jwg

+1

Hai ragione. Tuttavia, Popen e Call hanno argomenti molto simili, quindi queste soluzioni funzionano per entrambi. Ho inviato una modifica. – jhrf

+4

Si noti che da Python ver. 3.3 esiste in realtà un sottoprocesso.DEVNULL, che può essere usato al posto di 'open (os.devnull, 'wb')'. – EquipDev

19

Spesso questo tipo di chatter è su stderr, quindi si consiglia di disattivare anche quello. Ecco il mio esempio:

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

Nota:subprocess.DEVNULL è disponibile dal Python 3.3. Se siete ancora su Python 2:

import os 

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

notando che non si sta prendendo una decisione sull'uso di 'startupinfo' come mostrato qui: http://code.activestate.com/recipes/409002-launching-a-subprocess-without-a-console-window/ per evitare che la finestra lampeggi durante l'esecuzione python fuori da una console –

+0

python 3 ora ha 'sottoprocesso.DEVNULL' (ma la tua risposta è di 7 anni) –

+0

@ Jean-FrançoisFabre Questo è stato già menzionato su un commento sulla risposta accettata. Comunque, l'ho modificato adesso, grazie per il suggerimento. – wim

10

subprocess.call accettano anche redirezioni stdin/output/error:

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

[I documenti] (http://docs.python.org/2/library/subprocess.html#subprocess.call) specifica "Non utilizzare stdout = PIPE o stderr = PIPE con questa funzione". – mpen

+6

open() non restituisce un PIPE, il PIPE significa "sottoprocesso.PIPE" che può essere letto dall'altra parte nel programma. Un open di 'os.devnull' non causerà problemi perché non c'è un fondo in questo file di buchi neri, il buffer non verrà mai riempito. – BOYPT

+0

Ah. Ciò ha senso. Grazie! Non volevo usare 'Popen' perché restituisce un processo invece di un codice di stato. – mpen

1

Questa è una ricetta che uso molto: chiamare subprocess e raccogliere l'uscita, e quando il comando fa scartare l'output, ma quando fallisce, stampa l'output.

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

Io uso subprocess.check_output in questi casi e rilasciare il valore restituito. Potresti voler aggiungere un commento al tuo codice che indichi perché stai usando check_output al posto di check_call. check_output è anche più carino quando si verifica un errore e sei interessato all'output dell'errore. Esempio di codice qui sotto. L'output viene visualizzato solo quando si disapprova la linea di stampa. Se il comando fallisce, viene generata un'eccezione.

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

In che modo il rilascio del valore di ritorno impedisce l'uscita allo stdout? – Emre

+0

subprocess.check_output dovrebbe acquisire l'output e restituirlo. Stai vedendo un comportamento diverso? –

+0

Catturare e ignorare le opere, ma spreca memoria sul valore catturato che non viene mai utilizzato. Scartare l'output correttamente è più robusto. – tripleee

Problemi correlati