Кросс-платформенный / 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 есть другие способы решения этой проблемы.
Эндрю Айлетт

Ответы:

150

Как насчет os.devnull ?

import os
f = open(os.devnull,"w")
zookeeper.set_log_stream(f)
мсандеры
источник
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
>>> import os
>>> os.devnull
'nul'
Тихий призрак
источник
11
Для пояснения: в Windows указано «nul». Linux вернет '/ dev / null'.
Уолтер
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