什么是os.fdopen()语义?

时间:2014-04-09 15:04:55

标签: python linux macos python-2.7

我以前认为os.fdopen()要么吃文件描述符要么返回文件io对象,要么引发异常。

例如:

fd = os.open("/etc/passwd", os.O_RDONLY)
try: os.fdopen(fd, "w")
except: os.close(fd)  # prevent memory leak

然而,这些语义似乎并不总是存在。

以下是OSX上的一个示例:

In [1]: import os

In [2]: os.open("/", os.O_RDONLY, 0660)
Out[2]: 5

In [3]: os.fdopen(5, "rb")
---------------------------------------------------------------------------
IOError                                   Traceback (most recent call last)
<ipython-input-3-3ca4d619250e> in <module>()
----> 1 os.fdopen(5, "rb")

IOError: [Errno 21] Is a directory: '<fdopen>'

In [4]: os.close(5)
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-4-76713e571514> in <module>()
----> 1 os.close(5)

OSError: [Errno 9] Bad file descriptor

似乎os.fdopen()都吃了我的文件描述符5并引发了异常......

有没有一种安全的方法可以使用os.fdopen()

我错过了什么吗?

我找到了错误吗?

P.S。 Python版本字符串Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54),以防有人无法与他们一起复制。

P.P.S。 Py2.7 Linux也存在同样的问题。 然而,Py3.3没有出现上述问题。

1 个答案:

答案 0 :(得分:2)

Python检查生成的FILE*在创建python文件对象并将其存储在python对象中后不引用目录。由于目录检查中的错误,文件对象是deref(因为它不会被返回),这会导致调用析构函数来关闭文件。

我同意,如果文档显示它对传入的文件描述符有什么影响,那就太好了。我不确定你想要什么作为一个安全的&#39;使用fdopen的方法。如果您在失败时关闭文件描述符,那么python关闭了什么呢?只需使用

try: os.close(fd)
except: pass

以确定次要异常。

fill_file_fields调用<PyFile_FromFile来填充文件对象的成员,并在填充字段后调用dircheck函数。这会导致fill_file_fields返回NULL,因此PyFile_FromFile does Py_DECREF(f);其中f是文件对象。由于这是最后一个引用,因此调用deallocator file_dealloc,调用close_the_file(惊讶,惊讶)关闭文件。

在3.4分支中,dircheck是从fileio_init完成的,它使用标志变量fd_is_own来确定是否应该在错误条件下关闭文件。