我有一个带有内部数据库连接的对象,该对象在整个生命周期内都处于事件状态。在程序运行结束时,必须提交并关闭连接。到目前为止,我已经使用了显式的close方法,但这有点麻烦,尤其是当调用代码中可能发生异常时。

我正在考虑使用__del__方法进行关闭,但是在网上阅读后,我有些担心。这是有效的使用模式吗?我可以确定内部资源将在__del__中正确释放吗?

This discussion提出了类似的问题,但未找到满意的答案。我不想使用显式的close方法,也不愿使用with,因为我的对象不是像open-play-close那样简单地使用,而是作为另一个更大的对象的成员来使用的,在GUI中运行时使用它。

C++具有完美的析构函数,可以安全释放资源,因此我可以想象Python也达成了共识。由于某种原因,似乎并非如此,社区中的许多人都誓言反对__del__。那有什么选择呢?

最佳答案

您可以创建一个连接模块,因为模块在整个应用程序中保留相同的对象,并注册一个函数以使用 atexit 模块将其关闭

# db.py:
import sqlite3
import atexit

con = None

def get_connection():
    global con
    if not con:
        con = sqlite3.connect('somedb.sqlite')
    atexit.register(close_connection, con)
    return con

def close_connection(some_con):
    some_con.commit()
    some_con.close()

# your_program.py
import db
con = db.get_connection()
cur = con.cursor()
cur.execute("SELECT ...")

该建议是基于这样一个假设,即您的应用程序中的连接看起来像一个全局模块可以很好地提供的单个实例(单例)。

如果不是这种情况,则可以使用析构函数。

但是,析构函数与垃圾回收器和循环引用的配合不太好(必须在调用析构函数之前先删除循环引用),如果不是这种情况(需要多个连接),则可以使用析构函数。只是不要保留循环引用,否则您必须自己破坏它们。

另外,您对C++的说法是错误的。如果在C++中使用析构函数,则在定义对象的块完成时(例如python的with),或者在使用delete关键字(释放使用new创建的对象)时,将调用它们。除此之外,您必须使用不是析构函数的显式close()。因此,就像python一样-python甚至更“出色”,因为它具有垃圾回收器。

关于python - 在对象破坏时清理内部pysqlite连接,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/974813/

10-11 22:55