python内置插件open
和file
以一种我不太了解的方式与上下文管理器一起工作。
据我了解,open
会创建一个file
。 file
实现了上下文管理器方法__enter__
和__exit__
。我最初希望__enter__
实现文件描述符的实际打开。
但是,在open
块之外使用with
将返回已经打开的file
。因此,看起来file.__init__
或open
实际上是打开文件描述符,据我所知file.__enter__
没有做任何事情。或者file.__init__
/ open
可能会直接调用file.__enter__
吗?
第一个问题:
open
内置的执行流程是什么? open
处理什么,file.__init__
处理什么,file.__enter__
处理什么?在重复使用一个file
对象打开/关闭文件的多个周期时,这是如何工作的?这与为多个上下文循环重用其他上下文管理器对象有何不同?
第二个问题:
file
对象等对象具有设置步骤和拆卸步骤。设置在__init__
中进行,拆除发生在close
或__exit__
。
这是一个好的设计模式吗?是否应该为自定义函数/上下文管理器实现此设计模式?
答案 0 :(得分:2)
如果你查看_pyio.py(io模块的纯Python实现),你会在类IOBase中找到以下代码:
### Context manager ###
def __enter__(self): # That's a forward reference
"""Context management protocol. Returns self (an instance of IOBase)."""
self._checkClosed()
return self
def __exit__(self, *args):
"""Context management protocol. Calls close()"""
self.close()
这包含大多数问题的答案。需要了解的重要一点是,上下文管理器的功能是确保在完成文件后关闭文件。它只需调用close
函数即可完成此操作,这样可以省去这样做的麻烦。
file.__enter__
处理什么?没有。它只是返回一个文件对象,它是调用内置函数open()的结果。
在打开和关闭文件的多个循环中使用一个文件对象时,这是如何工作的?上下文管理器对于此目的不是很有用,因为每次都必须显式打开文件。
这是一个好的设计模式吗?是的,因为它减少了你必须编写的代码量,所以很容易阅读和理解。
是否应该为自定义函数/上下文管理器实现此模式?每当你有一个需要清理的对象,或者有一些涉及某种开/关概念的用法时,你应该考虑这种模式。标准库还有许多其他例子。
答案 1 :(得分:1)
问题1
在CPython中, open()除了创建文件对象外,其他基础C类型为 PyFileObject ;请参阅bltinmodule.c和fileobject.c
中的源代码static PyObject *
builtin_open(PyObject *self, PyObject *args, PyObject *kwds)
{
return PyObject_Call((PyObject*)&PyFile_Type, args, kwds);
}
file.__init__
会打开文件
file.__enter__
除了对字段file.fp
执行空白检查外,确实什么都不做
file.__exit__
调用close()
方法关闭文件
问题2
为什么file
这样设计是由于历史原因。
打开和带是在不同版本的CPython上引入的两个不同的关键字。在Python 2.5中引入了 with (参见PEP 343)。那时,打开已经使用了很长时间。
对于我们的自定义类型,我们可以设计为文件,具体取决于具体的应用程序上下文。
例如, threading.Lock 是一种不同的设计,其 init 和输入是分开的。