Wieloplatformowy / dev / null w Pythonie


85

Używam następującego kodu, aby ukryć stderr w systemie Linux / OSX dla biblioteki Python, której nie kontroluję, która domyślnie zapisuje do stderr:

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

Czy istnieje łatwa wieloplatformowa alternatywa dla / dev / null? Idealnie byłoby, gdyby nie zużywał pamięci, ponieważ jest to długotrwały proces.



8
@msw: Nie sądzę, Python ma więcej sposobów radzenia sobie z tym problemem.
Andrew Aylett

Odpowiedzi:



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

zookeeper.set_log_stream(Devnull())

Otwarcie też os.devnulljest w porządku, ale w ten sposób każda operacja wyjściowa jest wykonywana (jako noop) „w toku” - bez przełączania kontekstu na system operacyjny iz powrotem, a także bez buforowania (podczas gdy pewne buforowanie jest normalnie używane przez an open), a zatem jeszcze mniejsze zużycie pamięci.


6
Rozumiem, że używanie os.devnull może powodować pewne obciążenie. Ale jeśli ktoś użyje twojego obiektu, co jeśli obiekt zookeeper writewywoła inne metody niż jego obiekt pliku log_stream? Może wywołuje writelinesmetodę? Wtedy jest wyjątek.
cud173

5
To nie działa, gdy potrzebujesz prawdziwego pliku, np fileno(). Z rozszerzeniem .
Jonathon Reinhart

@JonathonReinhart W tym celu przypuszczam, że możesz leniwie utworzyć deskryptor pliku na żądanie, używając os.open(os.devnull, os.O_RDWR)tego samego fd dla kolejnych wywołań fileno(ponieważ i tak wszystkie dane są odrzucane)
minmaxavg

Będziesz także potrzebowaćclose()
shoosh

5
>>> import os
>>> os.devnull
'nul'

11
Dla wyjaśnienia: w systemie Windows podano „nul”. Linux zwróci „/ dev / null”.
Walter

5

Utworzyć własny obiekt przypominający plik, który nic nie robi?

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

1
Idiomatycznie masz rację, ale „self” to tylko kolejny parametr i zostanie przekazany jako pierwszy element funkcji args. Ponieważ nie stosujemy żadnego z parametrów, jedynym powodem do dbałości jest estetyka. Naprawię to ...
Andrew Aylett

2
Niektóre operacje wymagają również „fileno”
Jonathan Hartley

2

Ostrzeżenie o niedrogim rozwiązaniu!

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

Dla zabawy dorzuciłem dekorator: D
badp

Potrzebujesz też wejść i wyjść ?
user48956
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.