IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Disparition d'objets entre l'appel et le retour d'une fonction [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Inscrit en
    Novembre 2008
    Messages
    424
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 424
    Par défaut Disparition d'objets entre l'appel et le retour d'une fonction
    Bonjour,

    J'ai une classe dans laquelle je charge une structure à partir d'un fichier
    Tous les objets relatifs à la structure sont dans un module

    Lorsque je charge cette structure, tous mes logs au cours de ce chargement semblent indiquer que tout se passe bien.
    Mais une fois revenu dans la fonction appelante, tous les objets ont disparu

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    import traceback
    import os
    import Config.Parameters as Prm
    import DecEnr
    import logging
     
    os.environ['BASE_DIR'] = os.getcwd()
     
    class DecEnrParser:
        def __init__(self, parameter_file='./DecEnrParser.yml'):
            Prm.load(parameter_file)
            self.init_logger()
            self.dec_enr_structure = DecEnr.Structure()
            self.dec_enr_structure.load()                       ### Chargement de la structure, le log à la fin de cette méthode est plus bas (log 1)
            logging.debug("{}".format(self.dec_enr_structure))  ### <<< Le résultat de ce log est un peu plus bas (log 2)
    N'étant pas très au point sur les modules, je mets ici le contenu du fichier __init__.py contenu dans le répertoire DecEnr

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    from .Structure import *
    from .Record import *
     
    # J'ai aussi essayé en ajoutant tous les objets du module
    from .Cellule import *
    from .CellulesCollection import *
    from .Zone import *
    from .ZoneCollection import *
    En gros, la structure contient une collection de cellules (en fait un dictionnaire encapsulé dans un objet)
    Les cellules sont elles-mêmes des objets contenant chacune une collection de zones, chaque zone étant un objet...

    Voici le début du fichier relatif à la structure avec la méthode de chargement (load)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    import csv
    from .CellulesCollection import *
    from .Zone import *
    from .Cellule import *
    import Config.Parameters as Prm
     
    class Structure:
        def __init__(self):
            csv.register_dialect('excel_french', excel_french)
            self.cellules = CellulesCollection()
     
        def __repr__(self):
            return str(self.cellules)
     
        def load(self): # Procédure de chargement des données qui semble bien se passer
            with open(Prm.get('structure/filename'), encoding=Prm.get('structure/encoding')) as inf:
                cr=csv.reader(inf, 'excel_french')
                is_struct_part = False
                for i, csv_row in enumerate(cr):
                    if i==0:
                        header = self.map(csv_row)
                    else:
                        row = dict(zip(header, csv_row))
                        if row["Orig"] == 'Fichier':
                            zone = Zone(row)
                            self.cellules.add(zone)
            self.cellules.update_pos()
            self.cellules.update_len()
            logging.debug("{}".format(self))  ### <<< Le résultat de ce log est un peu plus bas (log 1)

    LOG 1 : à la fin du chargement de la structure. Tout est nickel.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    2021-02-03 13:28:53,882 [INFO] Structure.py - load :  Cellule Cellule01
    > CEL-TYP : 2 - 1 2
    > LIG-NUM : 2 - 3 2
    > TRM-FRI : 2 - 5 59
      > EME-IDT : 3 - 5 15
      > PAR-IDT : 3 - 20 9
      > LOT-DTJ : 3 - 29 9
    [...]
    Cellule Cellule02
    > CEL-TYP : 2 - 1 2
    > NEC-FAC : 2 - 3 6
      > SLM-IDT : 3 - 3 5
        > SLM-NRO : 4 - 3 3
        > CLM-COD : 4 - 6 2
    [...]
    LOG 2 : au retour de la fonction
    Les clés du dictionnaire de la Collection de cellule sont toujours là mais plus le contenu
    Je n'arrive pas à comprendre comment ce contenu disparaît entre la fin de la fonction de chargement et le retour de cette fonction.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    2021-02-03 13:28:53,884 [INFO] Record.py - __init__ :  Cellule Cellule01
    Cellule Cellule02
    Cellule Cellule04
    Cellule Cellule05
    Cellule Cellule06
    Je ne comprends pas ce qu'il se passe ici. Problème avec l'implémentation d'un module ?

    EDIT:
    Ce n'est pas lié à l'utilisation des modules.
    En mettant tous les fichiers sources dans le même répertoire, j'ai le même problème.

  2. #2
    Membre éclairé

    Inscrit en
    Novembre 2008
    Messages
    424
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 424
    Par défaut
    L'erreur venait d'un itérateur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
        def __iter__(self):
            self.idx=0 ### <= Cette ligne avait été oubliée
            return self
     
        def __next__(self):
            try:
                self.idx += 1
                return self.zones_list[self.idx - 1]
            except IndexError:
                raise StopIteration
    Résultat, lors du premier log, cette classe parcourait les éléments et lors du second... l'index n'était pas réinitialisé.

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 743
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 743
    Par défaut
    Salut,

    En voilà un joli problème...

    Si le comportement n'est pas le même c'est qu'il y a un effet de bord de... (à trouver)

    Mais çà amène à se poser des questions sur ce qui est supposé remonter du str(self.cellules)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        def __repr__(self):
            return str(self.cellules)
    et aussi avec le type de bibliothèques qui sont en dessous.

    note: si on dit que Python ne fait pas çà, on peut se poser de questions sur une extension C qui foutrait le bazar en dessous.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre éclairé

    Inscrit en
    Novembre 2008
    Messages
    424
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 424
    Par défaut
    De fait... Ta supposition est bonne puisque c'est dans les objets mis en branle par l'affichage des cellules que se trouvait l'itérateur non réinitialisé.

    Ici, il s'agit d'un tout petit projet et j'en profite pour faire des expériences.
    Le str(self.cellules) affiche la collection de cellules.
    Elle même a une fonction __repr__ qui fait un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class CellulesCollection:
        def __init__(self):
            self.cellules_dico = {}
     
        def __repr__(self):
            return "\n".join([str(val) for val in self.cellules_dico.values()])
    Les cellules elles même affichant une collection de zones (__repr__ également) et enfin, au niveau de la zone, on a des données relatives à des champs string.
    C'est dans la collection de zones que j'avais un itérateur qui ne marchait pas.

    Jusqu'à présent, je faisais plutôt des fonctions avec des yield si bien que je n'avais pas rencontré ce soucis. Mais c'était l'occasion de tenter.
    Alors je ne sais pas si des __repr__ "imbriqués" comme ça sont une bonne façon de faire mais en tout cas, c'est très efficace pour afficher mes données :-)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    class Cellule:
        def __init__(self, name):
            self.tree_init_level = 2
            self.name = name
            self.zones = ZoneCollection()
     
        def __repr__(self):
            return "\n".join(["Cellule {}".format(self.name)] + [str(z) for z in self.zones])
     
    # ...
    class ZoneCollection:
        class UnexpectedLevelError(Exception):
            pass
     
        def __init__(self):
            self.tree_init_niv = 2
            self.idx = 0
            self.zones_list = []
            self.zones_tree = []
     
        def __iter__(self):
            self.idx=0
            return self
     
        def __next__(self):
            try:
                self.idx += 1
                return self.zones_list[self.idx - 1]
            except IndexError:
                raise StopIteration
     
     
        def __repr__(self):
            return "\n".join([str(val) for val in self.zones_tree])

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 743
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 743
    Par défaut
    Bravo d'avoir su faire quelque chose de ce que j'ai pu raconter.

    Citation Envoyé par fatbob Voir le message
    Alors je ne sais pas si des __repr__ "imbriqués" comme ça sont une bonne façon de faire mais en tout cas, c'est très efficace pour afficher mes données :-)
    On fait ce qu'on veut (avec les __repr__) néanmoins pour afficher des données, __str__ serait plus approprié (voir comment ils racontent à dans la doc.).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/12/2008, 02h10
  2. Réponses: 3
    Dernier message: 19/10/2008, 20h14
  3. Argument d'appel de procédure à partir d'une fonction
    Par electrosat03 dans le forum VBA Access
    Réponses: 4
    Dernier message: 30/03/2008, 17h33
  4. Réponses: 5
    Dernier message: 28/02/2008, 14h35
  5. [langage] appel d'un tableau dans une fonction
    Par donny dans le forum Langage
    Réponses: 11
    Dernier message: 13/11/2006, 16h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo