我正在开发一个类似连接的对象,它实现了一个上下文管理器。强烈建议写这样的东西:
with MyConnection() as con:
# do stuff
当然也可以这样做:
con = MyConnection()
# do stuff
con.close()
但未能关闭连接是相当有问题的。所以关闭__del__()
似乎是一个好主意:
def __del__(self):
self.close()
这看起来很不错,但有时会导致错误:
Exception ignored in: [...]
Traceback (most recent call last):
File "...", line xxx, in __del__()
TypeError: 'NoneType' object is not callable
有时候,当调用__del__()
时,close方法已被破坏。
所以我正在寻找一种很好的方法来鼓励python在销毁时正确关闭连接。如果可能,我希望避免close()
和__del__()
答案 0 :(得分:4)
如果你真的想阻止用户不关闭连接,你只能在__enter__
中初始化它,或者你可以添加一个标记,发现它尚未被上下文管理器初始化。例如,像
class MyConnection(object):
safely_initialized = False
def __enter__(self):
# Init your connection
self.safely_initialized = True
return self
def do_something(self):
if not self.safely_initialized:
raise Exception('You must initialize the connection with a context manager!')
# Do something
def __exit__(self, type, value, traceback):
# Close your connection
这样,除非在上下文管理器中,否则不会初始化连接。
答案 1 :(得分:3)
无法保证__del__
实际运行的时间。由于您使用的是with
语句,请改用__exit__
方法。无论语句如何完成(通常,例外情况等),__exit__
语句完成后都会调用with
。
答案 2 :(得分:1)
您可以尝试在close
中调用__del__
,并忽略任何例外:
del __del__(self):
try:
self.close()
except TypeError:
pass
答案 3 :(得分:0)
确实,你不能强迫你的用户使用良好的编程技巧,如果他们拒绝这样做,你就不能对他们负责。
无法保证何时调用__del__
- 在某些Pythons中它是立即的,在其他Pythons中它可能不会在解释器关闭之前发生。因此,虽然不是一个很好的选择,但使用atexit可能是可行的 - 只需确保您注册的功能足够智能,以检查资源是否已被关闭/销毁。
答案 4 :(得分:0)
weakref.finalize()
允许您在对象被垃圾回收或程序退出时执行操作。它从 Python 3.4 开始可用。
当您创建对象时,您可以调用 <div>
<div *ngFor="let post of postsList">
{{post}}
</div>
</div>
,为其提供一个回调来清理您的对象所拥有的资源。
Python 文档提供了 several examples of its use:
finalize()
以及表示临时目录的类的 this example,其内容在以下情况下被删除:
>>> import weakref
>>> class Object:
... pass
...
>>> kenny = Object()
>>> weakref.finalize(kenny, print, "You killed Kenny!")
<finalize object at ...; for 'Object' at ...>
>>> del kenny
You killed Kenny!
方法被调用以先发生者为准。
remove()