如果我有一个包装资源的类,例如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
答案 0 :(得分:3)
您需要提供__enter__
和__exit__
方法。请参阅PEP 343。
这个PEP为Python语言添加了一个新的声明“with” 可以分解try / finally语句的标准用法。
在此PEP中,上下文管理员提供
__enter__()
和__exit__()
在进入和退出主体时调用的方法 声明。
答案 1 :(得分:1)
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