Plattformübergreifend / dev / null in Python

83

Ich verwende den folgenden Code, um stderr unter Linux / OSX für eine Python-Bibliothek auszublenden, die ich nicht kontrolliere und die standardmäßig in stderr schreibt:

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

Gibt es eine einfache plattformübergreifende Alternative zu / dev / null? Im Idealfall wird kein Speicher belegt, da dies ein langwieriger Prozess ist.

Tristan
quelle
1
Mögliches Duplikat von / dev / null in Windows?
Msw
8
@msw: Ich glaube nicht, Python hat mehr Möglichkeiten, mit diesem Problem umzugehen.
Andrew Aylett

Antworten:

146

Wie wäre es mit os.devnull ?

import os
f = open(os.devnull,"w")
zookeeper.set_log_stream(f)
msanders
quelle
46
class Devnull(object):
    def write(self, *_): pass

zookeeper.set_log_stream(Devnull())

Das Öffnen os.devnullist natürlich auch in Ordnung, aber auf diese Weise erfolgt jede Ausgabeoperation (als Noop) "in Bearbeitung" - kein Kontextwechsel zum Betriebssystem und zurück und auch keine Pufferung (während eine gewisse Pufferung normalerweise von einem verwendet wird open) und somit noch weniger Speicherverbrauch.

Alex Martelli
quelle
6
Ich verstehe, dass die Verwendung von os.devnull einen gewissen Overhead verursachen kann. Aber wenn man Ihr Objekt verwendet, was ist, wenn das Zookeeper-Objekt andere Methoden writeals sein log_stream- Dateiobjekt aufruft ? Vielleicht ruft es die writelinesMethode auf? Dann gibt es eine Ausnahme.
Wunder173
5
Dies funktioniert nicht, wenn Sie eine echte Datei benötigen , z fileno(). B. eine mit .
Jonathon Reinhart
@ JonathonReinhart Dafür, nehme ich an, könnten Sie den Dateideskriptor auf Anfrage träge erstellen os.open(os.devnull, os.O_RDWR)und dieselbe fd für nachfolgende Aufrufe von fileno(da alle Daten sowieso verworfen werden) verwenden
minmaxavg
Sie werden auch brauchenclose()
shoosh
5
>>> import os
>>> os.devnull
'nul'
SilentGhost
quelle
11
Nur um zu verdeutlichen: 'nul' wird unter Windows angegeben. Linux gibt '/ dev / null' zurück.
Walter
5

Erstellen Sie Ihr eigenes dateiähnliches Objekt, das nichts tut?

class FakeSink(object):
    def write(self, *args):
        pass
    def writelines(self, *args):
        pass
    def close(self, *args):
        pass
Andrew Aylett
quelle
1
Idiomatisch haben Sie Recht, aber 'self' ist nur ein weiterer Parameter und wird als erstes Element von übergeben args. Da wir keinen der Parameter verwenden, ist der einzige Grund zur Sorge die Ästhetik. Ich werde es reparieren ...
Andrew Aylett
2
Einige Operationen benötigen auch "Fileno"
Jonathan Hartley
2

Günstige Lösungswarnung!

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
badp
quelle
Ich warf einen Dekorateur nur zum Spaß: D
Badp
Müssen Sie auch ein- und aussteigen ?
Benutzer48956