Domanda

Continuo a una cache di operazioni per svuotare (a memoria persistente) sul caso di una filigrana o di un oggetto di finalizzazione. Dal momento che è __del__ non è più garantito di essere chiamato su ogni oggetto, è il metodo più idoneo per agganciare una funzione simile (o __del__ stesso) in atexit.register (durante l'inizializzazione)?

Se non mi sbaglio, questo causare l'oggetto a cui il metodo è destinato a rimanere in giro fino al termine del programma. Questo non è probabile che sia un problema, ma forse c'è una soluzione più elegante?

Nota: Lo so usando __del__ non è l'ideale perché può causare eccezioni imprendibili , ma non riesco a pensare ad un altro modo di fare questo corto di cascata finalize() chiama tutto il percorso attraverso il mio programma. TIA!

È stato utile?

Soluzione

Se non è necessario l'oggetto per essere vivi al momento di eseguire il colore, è possibile utilizzare riferimenti deboli

Questo è simile alla soluzione proposta, ma invece di utilizzare un vero e proprio riferimento, memorizzare un elenco di riferimenti deboli, con una funzione di callback per eseguire il colore. In questo modo, i riferimenti non stanno andando a tenere in vita quegli oggetti, e non si incorrere in eventuali problemi di immondizia circolari con metodi __del__.

È possibile eseguire la lista dei riferimenti deboli di cessazione per irrigare manualmente qualsiasi ancora vivo, se questo deve essere garantito fatto a un certo punto.

Altri suggerimenti

Se si deve gestire le risorse il modo preferito è quello di avere una chiamata esplicita a un metodo close() o finalize(). Dai un'occhiata alla dichiarazione with a astratto che. Nel tuo caso il modulo weakref potrebbe essere un'opzione. L'oggetto in cache può essere garbage collection dal sistema e hanno il loro metodo di __del__() chiamato oppure finalizzare loro se sono ancora vivi.

Direi atexit o provare e vedere se è possibile refactoring del codice in essere in grado di esprimersi con un with_statement che si trova nel __future__ in 2.5 e 2.6 in per impostazione predefinita. 2.5 include un modulo di contextlib di semplificare le cose un po '. Ho fatto qualcosa di simile quando si utilizza Tempesta ORM di Canonical.

da futuro import with_statement

@contextlib.contextmanager
def start_transaction(db):
  db.start()
  yield
  db.end()

with start_transaction(db) as transaction:
  ...

Per un caso non-db, si può solo registrare gli oggetti per essere lavati con una globale e quindi usare qualcosa di simile. Il vantaggio di questo approccio è che mantiene le cose esplicito.

Inserire il seguente in un file chiamato destructor.py

import atexit

objects = []

def _destructor():
    global objects
    for obj in objects:
        obj.destroy()
    del objects

atexit.register(_destructor)

ora usarlo in questo modo:

import destructor

class MyObj(object):
    def __init__(self):
        destructor.objects.append(self)
        # ... other init stuff
    def destroy(self):
        # clean up resources here

Credo atexit è il modo di andare qui.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top