Крос-платформа / dev / null у Python


83

Я використовую наступний код, щоб приховати 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 є більше способів вирішити цю проблему.
Ендрю Айлетт,

Відповіді:



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

zookeeper.set_log_stream(Devnull())

os.devnullЗвичайно, відкриття теж прекрасне, але таким чином кожна вихідна операція відбувається (як noop) "в процесі" - немає перемикання контексту на ОС та назад, а також немає буферизації (хоча деяка буферизація зазвичай використовується an open) і, отже, ще менше споживання пам'яті.


6
Я розумію, що використання os.devnull може призвести до накладних витрат. Але якщо хтось використовує ваш об’єкт, що, якщо об’єкт writezookeeper викликає інші методи, то його об’єкт файлу 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

Я кинув декоратор просто для розваги: ​​D
badp

Також потрібно ввійти та вийти ?
користувач48956
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.