【问题标题】:Cross platform /dev/null in PythonPython中的跨平台/dev/null
【发布时间】:2010-05-28 14:34:08
【问题描述】:

我正在使用以下代码在 Linux/OSX 上为 Python 库隐藏 stderr,我无法控制默认情况下写入 stderr:

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

是否有一个简单的跨平台替代 /dev/null ?理想情况下,它不会消耗内存,因为这是一个长时间运行的进程。

【问题讨论】:

  • /dev/null in Windows?的可能重复
  • @msw:我不这么认为,Python 有更多方法可以处理这个问题。

标签: python


【解决方案1】:

os.devnull 怎么样?

import os
f = open(os.devnull,"w")
zookeeper.set_log_stream(f)

【讨论】:

    【解决方案2】:
    class Devnull(object):
        def write(self, *_): pass
    
    zookeeper.set_log_stream(Devnull())
    

    当然,打开os.devnull 也很好,但是这样每个输出操作(作为noop)都会“进行中”——没有上下文切换到操作系统并返回,也没有缓冲(虽然一些缓冲通常是由open 使用),因此内存消耗更少。

    【讨论】:

    • 我知道使用 os.devnull 可能会产生一些开销。但是,如果有人使用您的对象,如果 zookeeper 对象调用其他方法,那么它的 log_stream 文件对象的write 怎么办?也许它调用writelines 方法?然后有一个例外。
    • 这在你需要一个 real 文件时不起作用,例如一个fileno()
    • @JonathonReinhart 为此,我想您可以根据请求懒惰地创建文件描述符,使用 os.open(os.devnull, os.O_RDWR) 并为后续调用 fileno 产生相同的 fd(因为无论如何都会丢弃所有数据)
    • 你还需要close()
    • @shoosh 会继承io.IOBase 并像上面那样覆盖write() 吗?这将提供客户可能期望的所有方法。
    【解决方案3】:
    >>> import os
    >>> os.devnull
    'nul'
    

    【讨论】:

    • 只是澄清一下:'nul' 在 Windows 上给出。 Linux 将返回“/dev/null”。
    【解决方案4】:

    创建您自己的不做任何事情的类文件对象?

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

    【讨论】:

    • 习惯上,你是对的,但'self'只是另一个参数,将作为args的第一个元素传入。由于我们不使用任何参数,因此关心的唯一原因是美观。我会修复它...
    • 有些操作还需要'fileno'
    【解决方案5】:

    廉价解决方案警告!

    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
    • 还需要 enterexit ?
    猜你喜欢
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 2015-02-16
    • 2011-03-11
    相关资源
    最近更新 更多