2010-05-28 13 views
66

Sto utilizzando il seguente codice per nascondere stderr su Linux/OSX per una libreria Python non controllo che scrive su stderr per impostazione predefinita:Cross Platform/dev/null in Python

f = open("/dev/null","w") 
zookeeper.set_log_stream(f) 

Esiste un facile alternativa incrociata a/dev/null? Idealmente non consumerebbe memoria poiché questo è un processo di lunga durata.

+1

possibile duplicato (http://stackoverflow.com/questions/313111/dev-null-in-windows) – msw

+8

@msw [/ dev/null in Windows?]: Io non la penso così, Python ha più modi per affrontare questo problema. –

risposta

110

Che ne dici di os.devnull?

import os 
f = open(os.devnull,"w") 
zookeeper.set_log_stream(f) 
4
>>> import os 
>>> os.devnull 
'nul' 
+9

Giusto per chiarire: 'nul' è indicato su Windows. Linux restituirà '/ dev/null'. – Walter

41
class Devnull(object): 
    def write(self, *_): pass 

zookeeper.set_log_stream(Devnull()) 

apertura os.devnull è troppo bella, naturalmente, ma in questo modo ogni operazione di uscita si verifica (come noop) "in corso" - nessun cambio di contesto per il sistema operativo e la schiena, e anche nessun buffering (mentre un po 'di buffering è normalmente usato da un open) e quindi anche un minor consumo di memoria.

+6

Capisco che l'utilizzo di os.devnull possa produrre un sovraccarico. Ma se uno usa il tuo oggetto e se l'oggetto zookeeper chiama altri metodi, allora scriva il suo oggetto file log_stream? Forse chiama il metodo 'writelines'? Quindi c'è un'eccezione. – miracle173

+2

Questo non funziona quando è necessario un file * real *, ad es. uno con 'fileno()'. –

+0

@JonathonReinhart Per questo, suppongo che potresti creare il descrittore di file pigramente su richiesta, usando 'os.open (os.devnull, os.O_RDWR)' e producendo lo stesso fd per le successive chiamate a 'fileno' (dato che tutti i dati sono scartato comunque) – minmaxavg

5

Crea il tuo oggetto simile a un file che non fa nulla?

class FakeSink(object): 
    def write(self, *args): 
     pass 
    def writelines(self, *args): 
     pass 
    def close(self, *args): 
     pass 
+1

Idiomaticamente, hai ragione, ma 'self' è solo un altro parametro e verrà passato come primo elemento di 'args'. Dato che non usiamo nessuno dei parametri, l'unica ragione per cui preoccuparsi è estetica. Lo aggiusterò ... –

+1

Alcune operazioni richiedono anche 'fileno' –

1

Avviso soluzione conveniente!

class DevNull(): 
    def __init__(self, *args): 
    self.closed = False 
    self.mode = "w" 
    self.name = "<null>" 
    self.encoding = None 
    self.errors = None 
    self.newlines = None 
    self.softspace = 0 
    def close(self): 
    self.closed == True 
    @open_files_only 
    def flush(self): 
    pass 
    @open_files_only 
    def next(self): 
    raise IOError("Invalid operation") 
    @open_files_only 
    def read(size = 0): 
    raise IOError("Invalid operation") 
    @open_files_only 
    def readline(self): 
    raise IOError("Invalid operation") 
    @open_files_only 
    def readlines(self): 
    raise IOError("Invalid operation") 
    @open_files_only 
    def xreadlines(self): 
    raise IOError("Invalid operation") 
    @open_files_only 
    def seek(self): 
    raise IOError("Invalid operation") 
    @open_files_only 
    def tell(self): 
    return 0 
    @open_files_only 
    def truncate(self): 
    pass 
    @open_files_only 
    def write(self): 
    pass 
    @open_files_only 
    def writelines(self): 
    pass 

def open_files_only(fun): 
    def wrapper(self, *args): 
    if self.closed: 
     raise IOError("File is closed") 
    else: 
     fun(self, *args) 
    return wrapper 
+0

Ho gettato un decoratore solo per divertimento: D – badp

+0

Anche bisogno di __enter__ e __exit__? – user48956

+0

@ user48956 possibilmente; questa risposta ha quasi sei anni ... – badp