2013-02-06 12 views
9

Sto chiamando un programma java dal mio script Python, e sta emettendo molte informazioni inutili che non voglio. Ho cercato addind stdout=None alla funzione Popen:Ignorare l'output dal sottoprocesso.Popen

subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=None) 

Ma fa lo stesso. Qualche idea?

risposta

31

Dal 3.3 documentation:

stdin, stdout e stderr specificare standard input del programma eseguito, di serie output e handle di file di errore standard, rispettivamente. I valori validi sono PIPE, DEVNULL, un descrittore di file esistente (un numero intero positivo), un oggetto file esistente e Nessuno.

Quindi:

subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=subprocess.DEVNULL) 

Questo esiste solo in 3.3 e versioni successive. Ma la documentazione dice:

DEVNULL indica che verrà utilizzato il file speciale os.devnull.

E os.devnull esiste fino al 2.4 (prima che esistesse lo subprocess). Quindi, si può fare la stessa cosa manualmente:

with open(os.devnull, 'w') as devnull: 
    subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=devnull) 

Si noti che se si sta facendo qualcosa di più complicato che non rientra in una sola riga, è necessario tenere devnull aperto per l'intera vita del Popen oggetto, non solo la sua costruzione. (Cioè, mettere il tutto dentro la dichiarazione with.)

Il vantaggio di reindirizzare a /dev/null (POSIX) o NUL: (Windows) è che non si crea un tubo inutile, e, cosa ancora più importante, in grado di' t eseguire nei casi limite in cui il sottoprocesso blocca durante la scrittura su quella pipe.

Lo svantaggio è che, in teoria, subprocess potrebbe funzionare su alcune piattaforme che non lo è os.devnull. Se ti interessa solo CPython su POSIX e Windows, PyPy e Jython (che è la maggior parte di te), questo non sarà mai un problema. Per altri casi, prova prima di distribuire il tuo codice.

+0

+1: per devnull. Assicurati che 'devnull' rimanga aperto mentre il sottoprocesso è vivo (l'istruzione with implica altrimenti). L'ultimo paragrafo sembra non necessario: DEVNULL è implementato tramite os.devnull in CPython. os.devnull funziona con Jython. – jfs

+0

@ J.F.Sebastian: dopo 'check_call' (che si trova all'interno di' with'), 'devnull' non è più necessario. Ma sì, forse dovrei chiarire che per i casi d'uso più complessi che non rientrano in una singola riga, l'intera cosa deve essere all'interno di 'with', non solo di' Popen'. – abarnert

+0

@JFSebastian: Nel frattempo, per 'os.devnull', è effettivamente garantito che esista su ogni piattaforma su cui è in esecuzione il sottoprocesso, quindi non c'è bisogno di" controllare prima di usare ", o sai solo che esiste anche su Jython e quindi dovrei spostare Jython nella lista delle piattaforme che non hai bisogno di controllare? – abarnert

6

Dal documentation:

Con le impostazioni di default di None, si verificherà alcun reindirizzamento.

è necessario impostare stdout-subprocess.PIPE, quindi chiamare .communicate() e semplicemente ignorare l'output catturato.

p = subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=subprocess.PIPE) 
p.communicate() 

anche se ho il sospetto che l'utilizzo di più subprocess.call() che è sufficiente per le vostre esigenze:

subprocess.call(['java', '-jar', 'foo.jar'], stdout=subprocess.PIPE) 
+1

@sjtaheri: grazie per la correzione, l'ho applicato io stesso. –

+4

Generalmente, la creazione e l'ignoramento di una pipe funzionano, ma possono portare al blocco del processo figlio se fa troppa scrittura (e naturalmente potrebbe funzionare sul tuo sistema e fallire per uno dei tuoi utenti), quindi penso che non sia davvero t sicuro di chiamare semplicemente qui invece di 'comunicare'. Questo è praticamente il motivo per cui è stato aggiunto 'DEVNULL', quindi puoi solo" chiamare "e non preoccuparti. (Beh, è ​​lì per il caso un po 'più complicato, dove si imposta 'stderr = DEVNULL' ma non' stdout', e solo 'check_output'. Ma la stessa idea.) – abarnert

+0

@abarnert: Ah, non era a conoscenza che era stato aggiunto ; appena trovato nella documentazione di Python 3. –