“弱引用对象不再存在”是什么意思?

38 投票
3 回答
55379 浏览
提问于 2025-04-15 14:37

我在运行一段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 个回答

0

弱引用是一种特殊的引用方式,它不会阻止垃圾回收器删除所引用的对象。如果你想确保某个对象一直存在,就应该使用强引用(也就是普通的引用)。

否则,当所有普通引用都不再使用时,就不能保证这个对象是否还会存在。

2

这段代码提到的对象已经被垃圾回收了,也就是说它不再被使用,系统把它清理掉了。为了避免循环引用的问题,可以使用一种叫做“弱引用”的东西,这种引用不会阻止垃圾回收的发生。在这个例子中,有一个弱引用代理(weakref.proxy),它指向一个叫做searchengine.crawler的对象。

61

普通的,也叫强引用的引用,是指能够让被引用的对象保持活着的引用。在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是不会介意的(不过这样可能会让读者感到困惑)。

撰写回答