Python 上的 io.open() 和 os.open() 有啥区别?
Posted
技术标签:
【中文标题】Python 上的 io.open() 和 os.open() 有啥区别?【英文标题】:What's the difference between io.open() and os.open() on Python?Python 上的 io.open() 和 os.open() 有什么区别? 【发布时间】:2011-11-05 09:05:14 【问题描述】:我意识到我一直在使用的 open()
函数是 io.open()
的别名,而从 os
导入 *
会掩盖这一点。
通过io
模块和os
模块打开文件有什么区别?
【问题讨论】:
来自Python docs: 这个函数[os.open
]是为低级I/O设计的。对于正常使用,使用内置函数open()
,它返回一个带有read()
和wprite()
方法(以及更多)的文件对象。要将文件描述符包装在文件对象中,请使用fdopen()
。
这个问题应该标记为python3。在python2中open()
和io.open()
是不同的。
【参考方案1】:
在 Python 2 中,内置的 open 和 io.open 是不同的(io.open 更新并支持更多的东西)。在 Python 3 中,open 和 io.open 现在是同一个东西(它们摆脱了旧的内置 open),所以你应该总是使用 open。需要与 Python 2 和 3 兼容的代码可能有理由使用 io.open。
下面的代码来验证这一点。
import io
with io.open("../input/files.txt") as f:
text = f.read().lower()
with open('../input/files.txt', encoding='utf-8') as f2:
text2 = f2.read().lower()
print(type(f))
print(type(f2))
# <class '_io.TextIOWrapper'>
# <class '_io.TextIOWrapper'>
【讨论】:
【参考方案2】:数据库和系统应用程序开发人员通常使用open
而不是fopen
,因为前者可以更好地控制将内存内容写入其后备存储(即磁盘上的文件)的时间、内容和方式。
在类 Unix 操作系统中,open
用于打开常规文件、套接字端点、设备、管道等。对于每个成功的 open
函数调用,都会返回一个正的文件描述符编号。它提供了一致的 API 和框架来检查各种这些对象上的事件通知等。
不过,fopen
是标准 C 函数,通常用于打开常规文件并返回 FILE
数据结构。 fopen
,实际上,最终会调用open
。 fopen
足以满足正常使用,因为开发人员无需担心何时将内存内容刷新或同步到磁盘并且不需要事件通知。
【讨论】:
【参考方案3】:添加到现有答案:
我意识到我一直在使用的 open() 函数是 io.open() 的别名
open()
== io.open()
仅在 Python 3 中。在 Python 2 中它们是不同的。
虽然在 Python 中使用open()
,我们可以通过方便的read()
和write()
方法获得易于使用的文件对象,但在操作系统级别上,文件是使用文件描述符(或Windows 中的文件句柄)访问的。因此,os.open()
应该在后台隐式使用。在这方面我没有检查过 Python 源代码,但是在 Python 3.3 中为 open()
添加的 opener
参数的文档说:
可以通过将可调用对象作为opener 来使用自定义开启器。这 然后通过以下方式获得文件对象的基础文件描述符 使用 (file, flags) 调用 opener。 opener 必须返回一个打开的文件 描述符(将
os.open
作为 opener 传递会产生类似的功能 传递None
)。
所以os.open()
是open()
的默认打开器,如果需要更改文件标志或模式,我们还可以在其周围指定自定义包装器。请参阅documentation for open()
以获取自定义打开器的示例,该打开器打开相对于给定目录的文件。
【讨论】:
【参考方案4】:绝对的一切:
os.open()
采用 filename 作为字符串,file mode 作为属性的按位掩码,以及 可选参数 描述文件权限位,并以整数形式返回文件描述符。
io.open()
将 filename 作为字符串或将 文件描述符 作为整数,将 文件模式 作为字符串, 和 可选参数 描述文件编码、使用的缓冲、如何处理编码错误和换行符,以及当文件关闭时底层 FD 是否关闭,并返回 io.IOBase
的一些后代。
【讨论】:
【参考方案5】:os.open
与open()
from C in Unix 非常相似。除非您正在做一些更底层的事情,否则您不太可能想要使用它。它为您提供了一个实际的文件描述符(例如,一个数字,而不是一个对象)。
io.open
是您的基本 Python open()
以及您几乎一直想要使用的东西。
【讨论】:
这是否意味着如果我使用一些简单的 C 文件 IO 代码,在stdio
函数前添加 os.
,并将扩展名更改为 .py
,代码将执行而不会出错?
我非常怀疑它,但我很想看看它是怎么回事(只是不要破坏任何东西)。【参考方案6】:
io.open()
是文件 I/O 的首选高级接口。它将操作系统级别的文件描述符包装在一个对象中,您可以使用该对象以 Python 方式访问该文件。
os.open()
只是底层 POSIX 系统调用的包装器。它需要更少的符号(和更多的 POSIX-y)参数,并返回代表打开文件的文件描述符(一个数字)。它确实 not 返回一个文件对象;返回的值不会有read()
或write()
方法。
来自os.open()
documentation:
此函数适用于低级 I/O。对于正常使用,使用内置函数
open()
,它返回一个带有read()
和write()
方法(以及更多)的“文件对象”。
【讨论】:
虽然我不禁要问,为什么有人会选择 Python 进行低级 I/O? 也许 Python 是程序员最熟悉的语言。或者他们正在为另一个 Python 程序编写插件。 为什么不呢?低级操作并没有规定我们应该用什么语言来表达。 我的意思是,您确实想用 Python 编写低级代码,以及 其他高级代码,Python 是更适合。 @cdhowie 这是一个错误的二分法。您可能想要使用 Python 并执行系统的低级控制。 “不这样做会导致代码的可移植性、可读性和可维护性降低”也是错误的。相比什么?与 C 中相同的低级 API 交谈?不,通过 Python 与他们交谈会更便携、更易读。如果您的意思是“与使用高级接口相比”,那是一个有争议的问题,如果您需要做的(业务目标)涉及低级接口。低/高级 API != 低/高级语言。【参考方案7】:os.open()
方法打开文件file并根据flags设置各种flags,也可能根据mode设置它的mode。
默认模式为0777(八进制),先屏蔽掉当前的unmask值。
此方法返回新打开文件的文件描述符。
虽然,
io.open()
方法以字符串模式中指定的模式打开一个文件。它返回一个新的文件句柄,或者,如果出现错误,则返回 nil 加上一条错误消息。
希望对你有帮助
【讨论】:
以上是关于Python 上的 io.open() 和 os.open() 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
OS X 上的 Python 和 OpenSSL 版本参考问题
在 Mac OS X 上的 python 2.7 和 python 3.5 之间切换