测试人社区

关于python中__del__方法在数据库操作中的讨论

由于是公司内网系统的代码,图片这些暂无,问题如下:

在工作中用到了接口和界面等自动化测试,大部分断言需要调用数据库,这是大前提;
直入主题~
我在项目中写了一个configDB的模块专用于封装数据库操作,在最后写了个析构函数

def __del__(self):
    self.db.close()

就这个鬼,想法是在这个析构函数中加入日志的打印,记录数据库连接的关闭,蛋py该死的机制限制了这个想象,无法在析构函数中使用或调用open函数。。。
没办法,另辟蹊径,使用装饰器给__del__添加了功能,主要目的是加上打印日志的那句话,执行在析构函数执行之后。。 代码如下:

@decorator.dbclose_log
def __del__(self):
    self.db.close()

def dbclose_log(func):
    def wrapper(*args, **kwargs):
        wrapper.__name__ = func.__name__
        try:
            func(*args, **kwargs)
        except Exception:
            msg = traceback.format_exc()
            log.excute_log(error_msg=msg)

原装手打,100%还原

现在问题来了,使用装饰器后,成功或不成功的概率参半,错误提示就是析构函数不能使用open,所以现在非常懵逼,请各位大佬指教,这块如何才能完美使用。。
强迫症患者的心病,害怕发展成抑郁 :joy: :joy:

代码好歹格式化下,而且代码也不全,不好判断。你的open在其他地方提前打开保存不就好了?

输入的时候格式化了的,结果显示出来就这样了。。。
我现在是在__init__函数中连接数据库db对象并创建游标,然后在析构函数中做数据库对象的施放操作。log模块也是封装好了的。
大佬的意思是在其他函数中先打开目标日志文件,然后析构的时候执行写入和关闭文件吗?那么这样貌似就没法调用我封装好的日志模块了 :joy:

这样,我争取把内网相关代码弄出来请教,比较清楚

你应该先了解__del__的清理规则,不要总是追寻别的新方法,__del__在清理前会有一个救赎机会,就是finalize,可以利用finalize方法,声明一个open,在清理前进行自我救赎,比如:

class Wait:
    def __init__(self):
        self.name = tempfile.mkdtemp()
        self._finalizer = weakref.finalize(self,self.fin)

    def fin(self):
        with open("test.xml", 'r', encoding="utf-8") as f:
            print(f.read())
        
    def __del__(self):
        print("hello")

感谢大佬,我去了解一下这块机制。。

还有就是,我在方法里调用了logging模块,现在暂时是注释了的,看看怎么能改改结构设计呢

嗯,这个方案我们以后可以在开源项目中一起讨论