Partage
  • Partager sur Facebook
  • Partager sur Twitter

Erreur dans un constructeur de classe

    6 octobre 2010 à 11:28:51

    Bonjour

    Voilà le constructeur de ma classe qui prend comme argument un nom de fichier xml que je lit par la suite :

    # constructeur de la classe
    	def __init__(self, fichier = "vasprun.xml") :
    		""" constructeur : initialise le nom du fichier xml """
    		self.fichierXML = fichier
    
    		# ouverture du fichier xml
    		try:
    			f = open( self.fichierXML, "r" )
    		except IOError:
    			print("\nLe fichier " + self.fichierXML + " est introuvable !")
    		finally:
    			f.close()
    
    		# on parse le fichier xml :
    		self.xml = xml.dom.minidom.parse( self.fichierXML )
    
    		# variable de controle
    		self.motsClefsLus = False
    		self.kPointsLus   = False
    


    Je souhaiterais deux chose :
    • savoir si le fichier xml existe réellement avant de l'utiliser
    • s'il n'existe pas je voudrais que l'instance de l'objet ne soit pas créée.


    Du coup j'ai essayé d'écrire un bloc try, mais je ne sais pas du tout si c'est correct. Je peux aussi me faire un test de os.path.exists(path) mais je crois que les blocs try sont plus dans l'esprit de python.

    Par contre, le deuxième point, je ne sais pas du tout comment on fait.

    Merci pour vos conseils
    • Partager sur Facebook
    • Partager sur Twitter
      6 octobre 2010 à 11:47:13

      Le bloc try/catch pour tester l'existence d'un fichier, c'est pas tellement mieux qu'un simple appel à la fonction "exists" (plus concis). Ici, il a juste l'avantage de tester en plus si le fichier peut être lu ou non.

      En revanche, décider de ne pas créer une instance en cas d'erreur n'est pas très adroit (ni recommandable) : au mieux, tu peux lever une exception et faire en sorte que ta classe soit utilisable avec le mot-clé with , en définissant ses méthodes __enter__ et __exit__ , ce qui est plus élégant et lui donne un comportement plus pythonique.

      Il suffit de regarder ce que ça donne à l'utilisation pour s'en rendre compte :

      with MonParserXml(fichier) as parser:
          # Faire des trucs. 
          # si la création de l'instance a échoué, 
          # ce bloc n'est pas lu
      
      # bloc terminé, le parser est détruit et "garbage-collecté"
      

      • Partager sur Facebook
      • Partager sur Twitter
      Zeste de Savoir, le site qui en a dans le citron !
        6 octobre 2010 à 13:42:54

        Merci

        Le coup du with ce n'est pas encore de mon niveau en python ... et je ne voudrais pas imposer à l'utilisateur la syntaxe d'utilisation de la classe. A moins que tu aies un exemple simple je verrai plus tard.

        Donc j'ai mis ceci dans le constructeur :

        # constructeur de la classe
        	def __init__(self, fichier = "vasprun.xml") :
        		""" constructeur : initialise le nom du fichier xml """
        		self.fichierXML = fichier
        
        		# ouverture du fichier xml
        		if os.path.exists( self.fichierXML ):
        			# on parse le fichier xml :
        			print("\nFichier xml du calcul : " + self.fichierXML)
        			self.xml = xml.dom.minidom.parse( self.fichierXML )
        		else:
        			print("\nLe fichier " + self.fichierXML + " est introuvable !")
        
        		# variable de controle
        		self.motsClefsLus = False
        		self.kPointsLus   = False
        


        Par contre comme l'instance est créée, si j'appelle une méthode python crache beaucoup de choses forcément incompréhensibles. Pourquoi ce n'est recommandable de ne pas créer l'instance ? Et comment je peux faire un retour disans que le fichier n'est pas bon si on appelle une méthode ? Je crée une fonction controle que j'appelle en première ligne de chaque méthode et qui affiche un message si le fichier n'est pas bon ?
        • Partager sur Facebook
        • Partager sur Twitter
          6 octobre 2010 à 14:15:51

          Il est préférable de lever une exception lorsque quelquechose plante dans le constructeur : c'est à l'utilisateur de la classe de choisir ce qu'il doit faire dans ce cas là (et donc d'être prévenu par une exception).
          Si tu te contentes de gérer l'erreur silencieusement et ne pas créer l'objet, l'utilisateur risque de se retrouver à utiliser les méthodes d'un objet qui n'a pas été créé, ce qui est pire.

          Sinon pour ce qui est « d'imposer une syntaxe » : rendre ta classe compatible avec le mot-clé with, ce n'est pas « imposer » quoi que ce soit, c'est juste coller à un comportement attendu par l'utilisateur, d'autant plus lorsque ta classe va manipuler un flux qu'il faut ouvrir puis ne pas oublier de refermer (ici un fichier, mais ce serait pareil avec une connexion à un serveur par exemple).
          • Partager sur Facebook
          • Partager sur Twitter
          Zeste de Savoir, le site qui en a dans le citron !
            6 octobre 2010 à 15:31:04

            En python, on ne passe pas un nom de fichier, mais un "file object", l'avantage étant que tu peux le remplacer par n'importe quoi qui se comporte comme un fichier, par exemple un GzipFile, un StringIO, etc, ce qui rend ta classe de XML beaucoup plus utile.

            # pas top
            p = MonParserXml( "fichier.xml" )
            
            # mieux
            p = MonParserXml( open( "fichier.xml" ))
            p = MonParserXml( GzipFile( "fichier.xml.gz" ))
            p = MonParserXml( StringIO( donnees ))
            


            En bonus, si le fichier n'existe pas, c'est le open() qui jarte, donc ton instance n'est pas créée. Et comme le code appelant met un open(), il s'attend à devoir traiter les exceptions de fichiers. Par contre si le code appelant met un StringIO, là pas la peine.
            • Partager sur Facebook
            • Partager sur Twitter

            Erreur dans un constructeur de classe

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown