2009-09-26 17 views
10

Me postulo un código Python y me sale el siguiente mensaje de error:¿Qué significa que "objeto débilmente referenciado ya no existe"?

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

¿Alguien sabe lo que puede que significa?

P.S. Este es el código que producen el error:

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

Respuesta

19

Una referencia fuerte de AKA normal es aquella que mantiene vivo el objeto referido: en CPython, cada objeto mantiene el número de referencias (normales) que existen (conocido como "recuento de referencia" o RC) y se va tan pronto como el RC llegue a cero (la marca generacional ocasional y los pases de barrido también recogen "bucles de referencia" de vez en cuando).

Cuando no quiere que un objeto permanezca vivo simplemente porque otro se refiere a él, entonces utiliza una "referencia débil", una variedad especial de referencia que no incrementa el RC; ver the docs para más detalles. Por supuesto, dado que el objeto referido PUEDE desaparecer si no se lo menciona (¡el propósito del ref débil en vez de uno normal!), El objeto de referencia debe ser advertido si trata de usar un objeto eso se ha ido, y esa alerta se da exactamente por la excepción que estás viendo.

En su código ...:

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

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

tmp es una referencia normal a la conexión ... pero es una variable local, por lo que desaparece al final de __init__. El (curiosamente llamado ;-) cursor self.con permanece, PERO está implementado internamente para mantener solo una referencia DÉBIL a la conexión, por lo que la conexión desaparece cuando lo hace tmp. Por lo tanto, en __del__ falla la llamada al .close (ya que el cursor necesita usar la conexión para cerrarse).

solución más simple es el siguiente pequeño cambio:

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

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

También he tenido la oportunidad de utilizar con la conexión y act de cursor, pero Python no le importará si está dispuesta a intercambiar los (Dejarás perplejos a los lectores ;-).

1

referencias débiles son una forma de referencia que no impide que el recolector de basura de disponer el objeto referenciado. Si desea garantizar que el objeto continuará existiendo, debe usar una referencia fuerte (normal).

De lo contrario, no hay garantía de que el objeto existirá o no existirá después de que todas las referencias normales hayan salido del alcance.

+3

El problema es que no sé qué significa "débil" o "fuerte". Ni siquiera sé lo que significa la referencia. – Verrtex

1

El código hace referencia a una instancia que ya se ha recolectado como basura. Para evitar referencias circulares, puede usar una referencia débil que no es suficiente para evitar la recolección de basura. En este caso, hay un weakref.proxy (http://docs.python.org/library/weakref.html#weakref.proxy) en un objeto searchengine.crawler.

+0

¿Las referencias circulares realmente previenen GC en python? – recursive

+0

He leído que '__del __()' impide GC en caso de referencias circulares cuando está escrito en Python. –

+1

Bastien tiene razón: http://www.python.org/doc/3.0/reference/datamodel.html#object.__del__ que indica: << Las referencias circulares que son basura se detectan cuando el detector de ciclo de opción está habilitado (está activado por defecto), pero solo se puede limpiar si no hay métodos __del __() de nivel de Python involucrados. Consulte la documentación del módulo gc para obtener más información sobre cómo el detector de ciclo maneja los métodos __del __(), en particular la descripción del valor de la basura. >> – Francesco

Cuestiones relacionadas