是否可以使用os.open/read/write/close?

Ben*_*Ben 5 python file

我打算经常从许多不同的文件中读/写一小段信息.下面有些人为的例子表明,当使用os操作直接作用于文件描述符时,所花费的时间大大减少.除了文件对象的便利之外,我是否遗漏了任何缺点?

import os
import time

N = 10000
PATH = "/tmp/foo.test"

def testOpen():
    for i in range(N):
        with open(PATH, "wb") as fh:
            fh.write("A")

    for i in range(N):
        with open(PATH, "rb") as fh:
            s = fh.read()

def testOsOpen():
    for i in range(N):
        fd = os.open(PATH, os.O_CREAT | os.O_WRONLY)
        try:
            os.write(fd, "A")
        finally:
            os.close(fd)

    for i in range(N):
        fd = os.open(PATH, os.O_RDONLY)
        try:
            s = os.read(fd, 1)
        finally:
            os.close(fd)

if __name__ == "__main__":
    for fn in testOpen, testOsOpen:
        start = time.time()
        fn()
        print fn.func_name, "took", time.time() - start
Run Code Online (Sandbox Code Playgroud)

样品运行:

$ python bench.py 
testOpen took 1.82302999496
testOsOpen took 0.436559915543
Run Code Online (Sandbox Code Playgroud)

Tim*_*ers 1

我会回答,这样它就不会永远保持开放状态;-)

确实没什么可说的:正如您已经指出的,file对象更方便。在某些情况下,它也更实用。例如,它有自己的缓冲层来加速面向行的文本操作(例如file_object.readline())(顺便说一句,这也是它速度较慢的原因之一。)并且file对象力求在所有平台上以相同的方式工作。

但是,如果您不需要/不希望这样做,那么使用较低级别和 zippieros文件描述符函数没有任何问题。后者有很多,并非所有平台都支持所有选项,也不是所有平台都支持所有选项。当然,您有责任将自己限制在您关心的平台交集中的操作和选项子集(这通常适用于 中的所有函数os,而不仅仅是其文件描述符函数 - 该名称os强烈暗示它包含的内容可能取决于操作系统)。

对于 Python 2 和 3,差异是由于 Python 3 在所有平台上对“文本”和“二进制”模式进行了强烈区分。这是一个 Unicode 世界,如果file不指定预期的编码,对象的“文本模式”就没有意义。在 Python 3 中,如果文件以“文本模式”打开,则file对象读取方法返回一个对象(Unicode 字符串),但如果以“二进制模式”打开,则返回一个对象。对于 write 方法也是如此。strbytes

因为os文件描述符方法没有编码的概念,所以它们只能处理 Python 3 中的类似字节的对象(无论例如在 Windows 上文件描述符是否使用低级os.open() O_BINARYO_TEXT标志打开)。

实际上,在您给出的示例中,这仅意味着您必须更改

"A"
Run Code Online (Sandbox Code Playgroud)

b"A"
Run Code Online (Sandbox Code Playgroud)

请注意,您还可以b"..."在 Python 2 的最新版本中使用文字语法,尽管它在 Python 2 中仍然只是字符串文字。在 Python 3 中,它表示一种不同类型的对象 ( bytes),并且文件描述符函数仅限于写入和返回类似字节的对象。

但如果您使用“二进制数据”,则完全没有限制。如果您正在使用“文本数据”,则可能是(没有足够的信息来猜测您的具体情况)。