“弱引用对象不再存在”是什么意思?
我在运行一段Python代码时,出现了以下错误信息:
Exception exceptions.ReferenceError: 'weakly-referenced object no longer exists' in <bound method crawler.__del__ of <searchengine.crawler instance at 0x2b8c1f99ef80>> ignored
有没有人知道这是什么意思呢?
附注: 这是导致错误的代码:
import sqlite
class crawler:
def __init__(self,dbname):
tmp = sqlite.connect(dbname)
self.con = tmp.cursor()
def __del__(self):
self.con.close()
crawler = crawler('searchindex.db')
3 个回答
弱引用是一种特殊的引用方式,它不会阻止垃圾回收器删除所引用的对象。如果你想确保某个对象一直存在,就应该使用强引用(也就是普通的引用)。
否则,当所有普通引用都不再使用时,就不能保证这个对象是否还会存在。
这段代码提到的对象已经被垃圾回收了,也就是说它不再被使用,系统把它清理掉了。为了避免循环引用的问题,可以使用一种叫做“弱引用”的东西,这种引用不会阻止垃圾回收的发生。在这个例子中,有一个弱引用代理(weakref.proxy),它指向一个叫做searchengine.crawler的对象。
普通的,也叫强引用的引用,是指能够让被引用的对象保持活着的引用。在CPython中,每个对象会记录有多少个普通引用指向它,这个数字叫做“引用计数”(RC)。当这个计数变成零的时候,那个对象就会被清除掉(偶尔会有一些垃圾回收机制会处理“引用循环”的情况)。
如果你不想让一个对象因为另一个对象的引用而一直存在,就可以使用“弱引用”。弱引用是一种特殊的引用方式,它不会增加引用计数;想了解更多,可以查看官方文档。当然,由于被引用的对象如果没有其他引用就会消失(这正是弱引用的目的!),所以引用这个对象的地方需要被提醒,如果它试图使用一个已经消失的对象,这个提醒就是你看到的那个异常。
在你的代码中…:
def __init__(self,dbname):
tmp = sqlite.connect(dbname)
self.con = tmp.cursor()
def __del__(self):
self.con.close()
tmp
是对连接的一个普通引用……但它是一个局部变量,所以在__init__
结束时就会消失。名为self.con
的游标会保留,但它内部实现只持有对连接的一个弱引用,因此当tmp
消失时,连接也会消失。所以在__del__
中调用.close
时会失败(因为游标需要使用连接才能关闭自己)。
最简单的解决方案就是做以下小改动:
def __init__(self,dbname):
self.con = sqlite.connect(dbname)
self.cur = self.con.cursor()
def __del__(self):
self.cur.close()
self.con.close()
我还顺便把连接命名为con,把游标命名为cur,但如果你想交换这两个名字,Python是不会介意的(不过这样可能会让读者感到困惑)。