2010-05-28 12 views
66

estoy usando el siguiente código para ocultar stderr en Linux/OSX para una biblioteca de Python no controlo que escribe en stderr por defecto:Cruz plataforma/dev/null en Python

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

¿Existe una fácil alternativa de plataforma cruzada a/dev/null? Idealmente no consumiría memoria ya que este es un proceso de larga ejecución.

+1

posible duplicado de (http://stackoverflow.com/questions/313111/dev-null-in-windows) – msw

+8

@msw [/ dev/null en Windows?]: Yo no lo creo, Python tiene más formas de lidiar con este problema. –

Respuesta

110

¿Qué tal os.devnull?

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

Solo para aclarar: 'nul' aparece en Windows. Linux devolverá '/ dev/null'. – Walter

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

zookeeper.set_log_stream(Devnull()) 

Apertura os.devnull está muy bien también, por supuesto, pero de esta manera se produce cada operación de salida (como NOOP) "en proceso" - sin cambio de contexto para el sistema operativo y la espalda, y también sin almacenamiento en búfer (mientras que un almacenamiento en memoria intermedia normalmente se usa en un open) y, por lo tanto, consume menos memoria.

+6

Entiendo que el uso de os.devnull puede generar cierta sobrecarga. Pero si uno usa su objeto, ¿qué ocurre si el objeto zookeeper llama a otros métodos y luego 'write' de su objeto de archivo log_stream? ¿Tal vez llama al método 'writelines'? Luego hay una excepción. – miracle173

+2

Esto no funciona cuando necesita un archivo * real *, p. uno con 'fileno()'. –

+0

@JonathonReinhart Para eso, supongo que podrías crear el descriptor de archivo perezosamente bajo petición, usando 'os.open (os.devnull, os.O_RDWR)' y obteniendo el mismo fd para las llamadas posteriores a 'fileno' (ya que todos los datos son descartado de todos modos) – minmaxavg

5

Crea tu propio objeto similar a un archivo que no hace nada?

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

Idiomáticamente, tienes razón, pero 'self' es solo otro parámetro y se pasará como el primer elemento de 'args'. Como no usamos ninguno de los parámetros, la única razón para preocuparse es estética. Lo arreglaré ... –

+1

Algunas operaciones también necesitan 'fileno' –

1

Cheap solution warning!

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

Lancé un decorador solo por diversión: D – badp

+0

¿También necesito __enter__ y __exit__? – user48956

+0

@ user48956 posiblemente; esta respuesta tiene casi seis años ... – badp

Cuestiones relacionadas