Question

Je garde un cache de transactions flush (stockage persistant) sur le cas de finalisation de filigrane ou de l'objet. Depuis __del__ est pas garantie d'être appelé sur chaque objet, est l'approche appropriée pour raccorder une fonction similaire (ou elle-même __del__) dans atexit.register (lors de l'initialisation)?

Si je ne me trompe pas, ce faire l'objet auquel la méthode est liée à traîner jusqu'à la fin du programme. Ce ne devrait pas être un problème, mais peut-être il y a une solution plus élégante?

Note: Je sais que l'utilisation __del__ est non-idéale, car il peut provoquer des exceptions uncatchable , mais je ne peux pas penser à une autre façon de le faire à court de finalize() en cascade appelle tout au long de mon programme. TIA!

Était-ce utile?

La solution

Si vous n'avez pas besoin de votre objet d'être en vie au moment où vous effectuez la chasse d'eau, vous pouvez utiliser faibles références

Ceci est similaire à la solution proposée, mais plutôt que d'utiliser une vraie référence, stocker une liste de références faibles, avec une fonction de rappel pour effectuer la chasse d'eau. De cette façon, les références ne vont pas garder ces objets vivants, et vous ne rencontrerez aucun problème de déchets circulaires avec des méthodes de __del__.

Vous pouvez parcourir la liste des références faibles sur la fin pour purger manuellement tout encore en vie si cela doit être garantie fait à un certain point.

Autres conseils

Si vous devez gérer la façon ressources preferred est d'avoir un appel explicite à une méthode de close() ou finalize(). Jetez un oeil à la déclaration de with à abstraite. Dans votre cas, le module weakref pourrait être une option. L'objet mis en cache peut être des déchets collectés par le système et ont leur méthode __del__() appelé ou vous les finaliser si elles sont encore en vie.

Je dirais atexit ou essayer de voir si vous pouvez factoriser le code en pouvant être exprimées à l'aide d'un with_statement qui est dans le __future__ à 2.5 et 2.6 par défaut. 2.5 comporte un contextlib de module pour simplifier les choses un peu. Je l'ai fait quelque chose comme ça lors de l'utilisation ORM Storm Canonical.

de avenir with_statement import

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

with start_transaction(db) as transaction:
  ...

Pour un cas non-db, vous pouvez simplement enregistrer les objets à être rincée avec une approche globale, puis utiliser quelque chose de similaire. L'avantage de cette approche est qu'il garde les choses explicites.

Mettez ce qui suit dans un fichier appelé destructor.py

import atexit

objects = []

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

atexit.register(_destructor)

utiliser maintenant cette façon:

import destructor

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

Je pense que atexit est le chemin à parcourir ici.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top