2009-03-30 13 views
44

Ho un binario chiamato A che genera l'output quando chiamato. Se lo chiamo da una shell Bash, la maggior parte dell'output viene soppressa da A > /dev/null. Tutto l'output è soppresso da A &> /dev/nullSoppressione dell'output nelle chiamate Python agli eseguibili

Ho uno script python denominato B che deve chiamare A. Voglio essere in grado di generare output da B, eliminando tutti gli output da A.

Dall'interno B, ho provato os.system('A'), os.system('A > /dev/null'), e os.system('A &> /dev/null'), os.execvp('...'), ecc, ma nessuno di quelli sopprimere tutto l'output di A.

avrei potuto correre B &> /dev/null, ma che sopprime tutte B ' s anche la produzione e non voglio quello.

Qualcuno ha suggerimenti?

risposta

57

Se si dispone di Python 2.4, è possibile utilizzare the subprocess module:

>>> import subprocess 
>>> s = subprocess.Popen(['cowsay', 'hello'], \ 
     stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0] 
>>> print s 
_______ 
<hello> 
------- 
     \ ^__^ 
     \ (oo)\_______ 
      (__)\  )\/\ 
       ||----w | 
       ||  || 
+0

Ho provato questo e ha funzionato, grazie! – Lin

+57

+1 per Cowsay :) – MestreLion

+7

Questo si comporta male se l'output di stdout è illimitato. –

8

Come l'os.system() documenti menzionano, utilizzare il modulo subprocess, e, se ti piace, impostare stdout = open (os.devnull, 'w') (e forse lo stesso per stderr) quando si apre il sottoprocesso.

103
import os 
import subprocess 

command = ["executable", "argument_1", "argument_2"] 

with open(os.devnull, "w") as fnull: 
    result = subprocess.call(command, stdout = fnull, stderr = fnull) 

Se il comando non ha alcun argomento, si può solo fornire come una semplice stringa.

Se il comando si basa su funzionalità di shell come caratteri jolly, pipe o variabili di ambiente, è necessario fornire l'intero comando come stringa e specificare anche shell = True. Questo dovrebbe essere evitato, dal momento che rappresenta un rischio per la sicurezza se il contenuto della stringa non viene convalidato con attenzione.

+0

perché shell = True? –

+4

Poiché la domanda originale utilizza os.system e, non sapendo esattamente cosa sta facendo, shell = True è la traduzione più affidabile per quello. – DNS

+0

DNS, ho provato la tua soluzione e funziona perfettamente per me. Grazie! – Lin

1

So che è tardi per il gioco, ma perché non semplicemente reindirizzare l'output a/dev/null da os.system? Es .:

tgt_file = "./bogus.txt" 
os.sytem("d2u '%s' &> /dev/null" % tgt_file) 

Questo sembra funzionare per quelle occasioni in cui non si vuole affrontare subprocess.STDOUT.

+2

Perché usare os.system per le chiamate di sistema è deprecato. I moduli di sottoprocesso gestiscono questo in modo molto più elegante e sicuro – MestreLion

12

Se il tuo motore di ricerca ti porta a questa vecchia domanda (come me), tieni presente che l'uso di PIPE può portare a deadlock. Infatti, poiché le pipe sono bufferizzate, è possibile scrivere un certo numero di byte in una pipe, anche se nessuno lo legge. Tuttavia, la dimensione del buffer è finita. E di conseguenza se il tuo programma A ha un'uscita più grande del buffer, A sarà bloccato per iscritto, mentre il programma chiamante B attende la cessazione di A. Ma non, in questo caso particolare ... vedi i commenti sotto.

Ancora, consiglio di utilizzare Devin Jeanpierre e la soluzione DNS.

+0

È proprio vero? Penso che sia solo deadlock se usi call() o popen()/wait(), ma non popen()/communicate(). –

+0

Sì! Per citare il documento, "Nota I dati letti sono memorizzati in memoria, quindi non utilizzare questo metodo se la dimensione dei dati è ampia o illimitata." –

+0

"bufferizzato in memoria" non significa necessariamente che la pipe è deadlock. Il problema a cui si riferiscono nei documenti è che se un comando produce un sacco di output, tutto viene archiviato in memoria sull'heap di Python. Questo è ovviamente indesiderabile e potrebbe causare errori di memoria o prestazioni molto gravi, ma solo in casi estremi e non si verificheranno blocchi critici. – Clueless

0

io uso:

call(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE) 

dove comando è la stringa del comando + argomenti

perché questo funzioni è necessario importare il sottoprocesso

+1

Non sarà quello stallo? –

0

Se è necessario acquisire solo STDOUT, doesn' Se lo assegni a una variabile, fallo? Per esempio:

megabyte='' 
# Create a 1 MiB string of NULL characters. 
for i in range(1048576): 
    megabyte += '\0' 
fh=open('zero.bin','w') 
# Write an 8 GiB file. 
for i in range(8192): 
    print(i) 
    # Suppress output of 'write()' by assigning to a variable. 
    discard=fh.write(megabyte) 
fh.close() 

stavo creando un file di grandi dimensioni pari a zero-riempita a zero spazio libero sul mio disco rigido e ha scoperto che ogni chiamata a handle.write (stringa) sputare il numero di byte scritti. Assegnandolo a un valore abbreviato sopprimeva quell'output.

21

In Python 3.3 e versioni successive, subprocess supporta an option for redirecting to /dev/null. Per usarlo, quando si chiama .Popen e gli amici, specificare stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, come argomenti di parole chiave.

Quindi la risposta di DNS, riscritto per Python 3.3+, diventa

import subprocess 
command = ["executable", "argument_1", "argument_2"] 
result = subprocess.call(command, 
         stdout=subprocess.DEVNULL, 
         stderr=subprocess.DEVNULL) 

Dalla documentazione:

subprocess.DEVNULL¶

valore speciale che può essere utilizzato come stdin, stdout o stderr argomento per Popen e indica che il file speciale os.devnull sarà essere utilizzato.

Novità nella versione 3.3.

Per Python 3.0 a 3.2, è necessario aprire manualmente il dispositivo null utilizzando open(os.devnull), come scritto dal DNS.

+1

Sfortunatamente, 'sottoprocesso.DEVNULL' è disponibile solo in 3.3+. Questa risposta dovrebbe essere modificata con il codice di compatibilità (o un riferimento ad esso). Non c'è anche alcun motivo per usare 'shell = True'. – phihag

+0

@phihag: Non ho incluso il codice di compatibilità perché la risposta di DNS descrive adeguatamente come farlo senza 'sottoprocesso.DEVNULL'. Hai ragione su 'shell'; fisso. –

+0

questo è quello che ha funzionato per me, usando python3 –

0

Se non si desidera attendere il completamento del comando, ad esempio l'avvio di un'attività di backup, un'altra opzione è passarla attraverso bash, operazione che consente al reindirizzamento di funzionare normalmente.

Per esempio, a partire da un file audio utilizzando aplay:

import os 

def PlaySound(filename): 
    command = 'bash -c "aplay %s &> /dev/null &"' % (filename) 
    os.system(command) 

In questo modo posso generare un nuovo processo, non aspettare che finisca e impedire che la stampa al terminale. L'unico problema è che caricherà un'istanza di bash e il processo in esecuzione, fornendo un leggero sovraccarico.

Problemi correlati