Кросс-платформенный / dev / null в Python


85

Я использую следующий код, чтобы скрыть stderr в Linux / OSX для библиотеки Python, которую я не контролирую, которая по умолчанию записывает в stderr:

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

Есть ли простая кроссплатформенная альтернатива / dev / null? В идеале он не будет потреблять память, поскольку это длительный процесс.


1
возможный дубликат / dev / null в Windows?
msw

8
@msw: Я так не думаю, у Python есть другие способы решения этой проблемы.
Эндрю Айлетт

Ответы:



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

zookeeper.set_log_stream(Devnull())

Открытие os.devnullтоже нормально, но в этом случае каждая операция вывода происходит (как noop) «в процессе» - без переключения контекста на ОС и обратно, а также без буферизации (хотя некоторая буферизация обычно используется оператором open) и, следовательно, еще меньше потребление памяти.


6
Я понимаю, что использование os.devnull может вызвать некоторые накладные расходы. Но если кто-то использует ваш объект, что, если объект zookeeper вызывает другие методы, а не writeего файловый объект log_stream? Может это вызывает writelinesметод? Тогда есть исключение.
miracle173

5
Это не работает, когда вам нужен настоящий файл, например, с расширением fileno().
Джонатон Рейнхарт,

@JonathonReinhart Для этого, я полагаю, вы могли бы лениво создать файловый дескриптор по запросу, используя os.open(os.devnull, os.O_RDWR)и выдавая тот же fd для последующих вызовов fileno(поскольку все данные в любом случае отбрасываются)
minmaxavg

Вам также понадобитсяclose()
shoosh


5

Создать свой собственный файловый объект, который ничего не делает?

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

1
Идиоматично, вы правы, но «self» - это просто еще один параметр, который будет передан как первый элемент args. Поскольку мы не используем ни один из параметров, единственная причина для беспокойства - эстетическая. Я исправлю ...
Эндрю Айлетт

2
Некоторые операции также нуждаются в «fileno»
Джонатан Хартли

2

Предупреждение о дешевом решении!

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


Также нужно войти и выйти ?
user48956
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.