0

如果我有一个包装资源的类,例如sqlite数据库连接或文件,是否有办法with在我的对象超出范围或被收集时使用该语句关闭资源?

为了澄清我的意思,我想避免这种情况:

class x:
    def __init__(self):
        # open resource

    def close(self): # or __del__, even worst
        # close resource

但是以这样一种方式使资源始终被释放,如

with open('foo') as f:
    # use resource
4

3 回答 3

3

你需要提供__enter____exit__方法。参见PEP 343

此 PEP 向 Python 语言添加了一个新语句“with”,以便可以排除 try/finally 语句的标准用法。

在这个 PEP 中,上下文管理器提供了在进入__enter__()__exit__() 退出 with 语句主体时调用的方法。

于 2013-08-07T19:32:02.550 回答
1

使用contextlib.closing

with contextlib.closing(thing) as thing:
    do_stuff_with(thing)
# Thing is closed now.
于 2013-08-07T19:32:10.680 回答
1

您始终可以将所需的任何清理代码放入类的__del__方法中:

class x:
    def __init__(self):
        self.thing = get_thing()

    def __del__(self):
        self.thing.close()

但你不应该。

这是一个坏主意,有几个原因。如果您使用的是 CPython,__del__则拥有自定义方法意味着 GC 不能中断引用循环。如果您使用大多数其他 Python 实现,__del__则不会在可预测的时间调用方法。

这就是为什么您通常将清理放在显式close方法中的原因。这是你在课堂上能做的最好的事情。确保调用方法而不是类本身始终取决于类的用户。close

因此,您无法with在课堂上使用语句或任何等效的东西。with但是您可以通过将您的类变成上下文管理器,如 roippi 的回答中所述,或者只是建议他们contextlib.closing在您的文档中使用,从而使您的类的用户更容易使用语句。

于 2013-08-07T20:11:48.657 回答