web-dev-qa-db-fra.com

Charger un objet mariné dans un fichier différent - Erreur d'attribut

J'ai du mal à charger un fichier mariné dans un module différent du module où j'ai mariné le fichier. Je connais le fil suivant: Impossible de charger des fichiers à l'aide de modules de pickle et multipile . J'ai essayé la solution proposée d'importer la classe dans le module où je décompresse mon fichier, mais cela me donne toujours la même erreur: AttributeError: Can't get attribute 'Document' on <module '__main__' from ''>

La structure de base de ce que j'essaie de faire:

Utilisez un fichier qui décapage et décompresse des objets, utils.py:

import pickle

def save_document(doc):

    from class_def import Document

    write_file = open(file_path, 'wb')
    pickle.dump(doc, write_file)

def load_document(file_path):
    from class_def import Document

    doc_file = open(file_path, 'rb')
    return pickle.load(doc_file)

Fichier dans lequel l'objet Document est défini et la méthode save util est appelée, class_def.py:

import utils

class Document(object):
    data = ""

if __name__ == '__main__':
    doc = Document()
    utils.save_document(doc)

Fichier où la méthode de chargement est appelée, process.py:

import utils

if __name__ == '__main__':
     utils.load_document(file_path)

L'exécution de process.py donne l'attributError mentionné. Si j'importe le fichier class_def.py dans process.py et que j'exécute sa méthode principale comme mentionné dans le thread d'origine, cela fonctionne, mais je veux pouvoir exécuter ces deux modules séparément, car le fichier class_def est une étape de prétraitement qui prend tout à fait parfois. Comment pourrais-je résoudre ce problème?

18
lmartens

dans ton class_def.py fichier vous avez ce code:

if __name__ == '__main__':
    doc = Document()
    utils.save_document(doc)

Cela signifie que doc sera un __main__.Document objet, donc quand il est mariné, il s'attend à pouvoir obtenir une classe Document à partir du module principal, pour résoudre ce problème, vous devez utiliser la définition de Document à partir d'un module appelé class_def ce qui signifie que vous ajouteriez une importation ici:

if __name__ == '__main__':
    from class_def import Document 
    # ^ so that it is using the Document class defined under the class_def module
    doc = Document()
    utils.save_document(doc)

de cette façon, il devra exécuter le fichier class_def.py deux fois, une fois en tant que __main__ et une fois comme class_def mais cela signifie que les données seront décapées en tant que class_def.Document objet donc le charger récupérera la classe du bon endroit. Sinon, si vous avez un moyen de construire un objet document à partir d'un autre, vous pouvez faire quelque chose comme ça dans utils.py:

def save_document(doc):
    if doc.__class__.__module__ == "__main__":
        from class_def import Document #get the class from the reference-able module
        doc = Document(doc) #convert it to the class we are able to use


    write_file = open(file_path, 'wb')
    pickle.dump(doc, write_file)

Bien que d'habitude, je préfère la première façon.

17

J'ai eu un problème similaire et je viens juste de réaliser les différences entre nos implémentations.

Votre structure de fichiers:

  • util.py
    • définir les fonctions de décapage
  • class_def.py
    • import util
    • définir la classe
    • faire instance
    • appeler enregistrer le cornichon
  • process.py
    • import util
    • cornichon de charge

Mon erreur (en utilisant vos noms de fichiers) était la première:

  • util_and_class.py
    • définir la classe
    • définir des func cornichons
    • faire instance
    • appeler enregistrer le cornichon
  • process.py
    • import util_and_class
    • appelez pickle de chargement << ERREUR

Ce qui a résolu mon problème d'importation de cornichons:

  • util_and_class.py
    • définir la classe
    • définir des func cornichons
  • pickle_init.py
    • import util_and_class
    • faire instance
    • appeler enregistrer le cornichon
  • process.py
    • appeler la charge de cornichon

Cela a eu l'effet secondaire bienvenu que je n'avais pas besoin d'importer le fichier util_and_class car il est cuit dans le fichier pickle. L'appel de l'instance et l'enregistrement du cornichon dans un fichier séparé ont résolu le __name__ problème de "chargement d'un fichier décapé dans un module différent du module dans lequel j'ai décapé le fichier."

2
xtian