2009-09-26 54 views
10

我運行一個Python代碼,我收到以下錯誤信息:這是什麼意思「弱引用的對象不再存在」?

Exception exceptions.ReferenceError: 'weakly-referenced object no longer exists' in <bound method crawler.__del__ of <searchengine.crawler instance at 0x2b8c1f99ef80>> ignored 

是否有人知道這裏是什麼地方意味着什麼?

P.S. 這是產生誤差的代碼:

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') 

回答

19

正常AKA強引用是一個保持引用的目標活:在CPython的,每個對象保留的到它(正常)的引用存在(被稱爲它的「引用計數」或RC)的數量和進一旦RC達到零(偶爾分代標記和掃描通過也偶爾垃圾收集「參考循環」)。

當你不希望對象活着,只是因爲另外一個是指它,那麼你用一個「弱引用」,一個特殊的各種參考,不增加的RC;詳情請參閱the docs。當然,由於被引用對象CAN如果沒有被另外引用(弱引用的全部目的而不是正常引用),則引用對象CAN會消失 - ,如果引用對象嘗試使用對象,則需要警告引用對象那已經消失了 - 而且這種警報正是由你所看到的例外給出的。

在你的代碼...:

def __init__(self,dbname): 
    tmp = sqlite.connect(dbname) 
    self.con = tmp.cursor() 

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

tmp是正常參考連接...但它是一個局部變量,因此它在__init__末消失。 (特別命名的;-)光標self.con停留,但它在內部實現只能容納一個WEAK ref連接,所以當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會不會介意(你只會讓讀者感到困惑;-)。

1

弱引用是參考的形式,不阻止垃圾收集器從設置所述引用的對象。如果你想保證對象將繼續存在,你應該使用強(正常)引用。

否則,就不能保證對象會或不會畢竟正常的引用都超出範圍存在。

+3

的問題是,我不知道什麼是「弱」或「強」基準裝置。我甚至不知道參考文獻的含義。 – Verrtex 2009-09-26 20:49:32

1

的代碼指具有收集已經被垃圾一個實例。 爲避免循環引用,您可以使用不足以防止垃圾回收的弱引用。在這種情況下,對於searchengine.crawler對象有一個weakref.proxy(http://docs.python.org/library/weakref.html#weakref.proxy)。

+0

循環引用是否真的阻止了python中的GC? – recursive 2009-09-26 20:50:56

+0

我讀過'__del __()''在Python中編寫循環引用的情況下阻止GC。 – 2009-09-26 21:03:27

+1

Bastien是正確的:http://www.python.org/doc/3.0/reference/datamodel.html#object。__del__其中指出:<<選項週期檢測器啓用(默認情況下它處於啓用狀態)時檢測到循環引用是垃圾,但只能在沒有涉及Python級__del __()方法時清除。有關如何通過循環檢測器處理__del __()方法的更多信息,請參閱gc模塊的文檔,特別是垃圾值的描述。>> – Francesco 2009-09-26 21:21:20