如何打开句柄上下文管理?

问题描述 投票:2回答:2

python内置插件openfile以一种我不太了解的方式与上下文管理器一起工作。

根据我的理解,open将创造一个filefile实现了上下文管理器方法__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__

这是一个很好的设计模式吗?是否应该为自定义函数/上下文管理器实现此设计模式?

python file with-statement contextmanager
2个回答
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

在CPython中,open()除了创建一个文件对象之外什么都不做,底层C类型是PyFileObject;请参阅bltinmodule.cfileobject.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上引入的两个不同的关键字。随着Python 2.5的推出(见PEP 343)。那时,open已经使用了很长时间。

对于我们的自定义类型,我们可以设计像文件一样,取决于具体的应用程序上下文。

例如,threading.Lock是一个不同的设计,它的init和enter是分开的。

© www.soinside.com 2019 - 2024. All rights reserved.