我以前认为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没有出现上述问题。
答案 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
来确定是否应该在错误条件下关闭文件。