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对象进行多个打开/关闭文件的周期时,这是如何工作的?这与在多个上下文循环中重用其他contextmanager对象有什么不同?
第二个问题:
像file对象这样的对象有一个设置步骤和一个拆卸步骤。设置发生在__init__中,而拆卸发生在close或__exit__中.
这是一个很好的设计模式吗?应该为自定义函数/上下文管理器实现此设计模式吗?
发布于 2018-03-06 02:23:39
如果您查看_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()的调用的结果。
当使用一个文件对象进行多个打开和关闭文件的周期时,这是如何工作的?上下文管理器对此并不十分有用,因为每次都必须显式地打开文件。
这是一个很好的设计模式吗?是的,因为它减少了您必须编写的代码数量,所以很容易阅读和理解。
应该为自定义函数/上下文管理器实现此模式吗?当您有需要清理的对象时,或者有涉及某种类型的打开/关闭概念的用法时,您都应该考虑这种模式。标准库还有许多其他示例。
发布于 2018-03-06 02:25:58
问题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设计是由于一个历史原因。
open和with是在不同版本的CPython上引入的两个不同关键字。with是在Python2.5之前引入的(参见佩普343)。在那个时候,开放式已经被使用了很长时间。
对于我们的自定义类型,我们可以像文件那样进行设计,这取决于具体的应用程序上下文。
例如,threading.Lock是一个不同的设计,它的init和enter分别。
https://stackoverflow.com/questions/49122128
复制相似问题