2009-05-26 9 views
0

J'ai un programme qui traite plusieurs fichiers, et pour chaque fichier un rapport est généré. La partie générant le rapport est une fonction séparée qui prend un nom de fichier, puis retourne. Pendant la génération du rapport, les parties intermédiaires sont mises en mémoire cache, car elles peuvent être utilisées pour plusieurs parties du rapport, afin d'éviter tout recalcul. Lorsque j'exécute ce programme sur tous les fichiers d'un répertoire, il s'exécute pendant un certain temps, puis plante avec une erreur MemoryError. Si je le réexécute dans le même répertoire, il ignore tous les fichiers pour lesquels il a créé un rapport et continue. Il va traiter un couple de fichiers avant de se planter à nouveau.Python MemoryError - comment puis-je forcer la suppression d'un objet

Maintenant, pourquoi toutes les ressources ne sont-elles pas effacées, ou marquées au moins pour le garbage collection, après l'appel de méthode qui génère le rapport? Il n'y a aucune instance quittant, et je n'utilise aucun objet global, et après chaque traitement de fichier, tous les fichiers ouverts sont fermés.

Y at-il des moyens pour moi de vérifier qu'il n'y a pas de références supplémentaires à un objet? Existe-t-il un moyen de forcer la récupération de place en Python?

Un peu plus de détails sur l'implémentation et le cache. Chaque rapport comporte plusieurs éléments, chaque élément pouvant alors s'appuyer sur des calculs différents, chaque calcul pouvant dépendre d'autres calculs. Si un calcul est déjà fait, je ne veux pas le refaire (la plupart d'entre eux sont chers).

Voici une version abrégée de la mémoire cache:

class MathCache: 
    def __init__(self): self.cache = {} 
    def get(data_provider): 
     if not data_provider.id in self.cache: 
      self.cache[data_provider.id] = data_provider.get_value(self) 
     return self.cache[data_provider.id] 

Une instance de celui-ci est créé, puis transmis à chaque élément dans le rapport. Cette instance est uniquement conservée dans une référence locale dans la méthode de création de rapport.

Tous les fournisseurs de données héritent d'une classe commune qui sert à créer un ID unique pour l'instance en fonction d'un argument de hachage de constructeur et d'un nom de classe. Je transmets le MathCache car le data_provider peut lui-même s'appuyer sur d'autres calculs.

+0

Un peu plus de code serait utile. Les "parties intermédiaires sont mises en mémoire" est vague - et probablement la cause de votre problème. Python a un excellent ramassage des ordures. D'une certaine façon, vous empêchez cela. –

+0

Etes-vous sûr que les lignes 4 et 5 de votre exemple ont raison? Cela devrait jeter un KeyError. – bayer

+0

Je suppose que vous voulez dire self.cache [data_provide.id] = get_value (self) et non ".get_value (self)", non? – EOL

Répondre

Questions connexes