Eli*_*sky 7 python destructor pysqlite
我有一个内部数据库连接的对象,它在整个生命周期中都是活动的.在程序运行结束时,必须提交和关闭连接.到目前为止,我已经使用了一个显式close方法,但这有点麻烦,特别是当调用代码中发生异常时.
我正在考虑使用这种__del__方法来关闭,但经过一些在线阅读后我有所顾虑.这是一种有效的使用模式吗?我可以确定内部资源是否可以__del__正确释放?
这次讨论提出了类似的问题但没有找到令人满意的答案 我不想有一个显式的close方法,并且使用with不是一个选项,因为我的对象不像开放式播放关闭那样简单,而是作为另一个更大的对象的成员保存,使用它在GUI中运行时.
C++有完美的工作析构函数,可以安全地释放资源,所以我认为Python也有同意的东西.由于某种原因,似乎并非如此,社区中的许多人发誓反对__del__.那么替代方案是什么?
阅读with声明.您正在描述其用例.
您需要将连接包装在"Context Manager"类中,该类处理语句使用的__enter__和__exit__方法with.
有关更多信息,请参阅PEP 343.
编辑
"我的对象并不像开放式游戏那样简单,而是作为另一个更大的对象的成员保留"
class AnObjectWhichMustBeClosed( object ):
def __enter__( self ):
# acquire
def __exit__( self, type, value, traceback ):
# release
def open( self, dbConnectionInfo ):
# open the connection, updating the state for __exit__ to handle.
class ALargerObject( object ):
def __init__( self ):
pass
def injectTheObjectThatMustBeClosed( self, anObject ):
self.useThis = anObject
class MyGuiApp( self ):
def run( self ):
# build GUI objects
large = ALargeObject()
with AnObjectWhichMustBeClosed() as x:
large.injectTheObjectThatMustBeClosed( x )
mainLoop()
Run Code Online (Sandbox Code Playgroud)
有些人称之为"依赖注入"和"控制反转".其他人称之为战略模式."ObjectThatMustBeClosed"是一种策略,插入一些更大的对象.程序集是在GUI应用程序的顶层创建的,因为这通常是获取数据库等资源的地方.
您可以创建一个连接模块,因为模块在整个应用程序中保留相同的对象,并注册一个函数以使用该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 ...")
Run Code Online (Sandbox Code Playgroud)
这种假设是基于这样的假设:应用程序中的连接看起来像是一个模块全局提供的单个实例(单例).
如果不是这样,那么你可以使用析构函数.
但是,析构函数与垃圾收集器和循环引用不一致(您必须在调用析构函数之前自己删除循环引用),如果不是这种情况(您需要多个连接),那么您可以使用析构函数.只是不要保持循环引用或你必须自己打破它们.
另外,你对C++的看法是错误的.如果在C++中使用析构函数,则在定义对象的块完成时(如python with)或使用delete关键字(取消分配创建的对象new)时调用它们.除此之外,您必须使用close()不是析构函数的显式.所以它就像python-python甚至"更好",因为它有一个垃圾收集器.