在包装资源的类中使用with语句

时间:2013-08-07 19:30:27

标签: python resources with-statement

如果我有一个包装资源的类,例如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

3 个答案:

答案 0 :(得分:3)

您需要提供__enter____exit__方法。请参阅PEP 343

  

这个PEP为Python语言添加了一个新的声明“with”   可以分解try / finally语句的标准用法。

     

在此PEP中,上下文管理员提供__enter__()__exit__()   在进入和退出主体时调用的方法   声明。

答案 1 :(得分:1)

使用contextlib.closing

with contextlib.closing(thing) as thing:
    do_stuff_with(thing)
# Thing is closed now.

答案 2 :(得分: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