Quand privilégier les exceptions ?

Quand privilégier les exceptions ? - Python - Programmation

Marsh Posté le 28-01-2015 à 18:37:58    

Bonjour, je débute et au cours d'un TP (openclassroom) je dois par exemple:
- Lire/Ecrire dans un fichier

 

Pour lire le fichier, je me suis dis que le fichier peut ne pas exister et donc lever une exception FileNotFoundError
Ainsi je
try: lire le fichier
except: créer le fichier # puisqu'il n'existe pas

 

Hors dans la correction du TP on procède tout simplement ainsi:
if os.path.exists

 

Du coup, quand dois-je utiliser les exceptions ?
- Si et seulement si il n'existe pas de moyen de vérifier l'information par Python ou un de ses modules ?
- Si et seulement si je dois traiter des données entrée par un utilisateur ?

 

Bref j'en comprends bien l'utilité mais j'ai du mal à comprendre QUAND l'utiliser, car je peux toujours vérifier mon code jusque là et contrôler les données sans avoir à passer par des exceptions mais des if. Puis placer des if partout est plus jolie que des try except.

 

Merci

 

Edit: Je viens de tomber d'ailleurs sur une autre source, qui dit que pour vérifier l’existence d'un fichier c'est bien mieux de passer par les exceptions car avec des if, il faudrait
Vérifier que le fichier existe.
Vérifier que le fichier est un fichier et non un dossier.
Vérifier que j’ai les permissions d’écrire sur le fichier.
Vérifier que j’ai les permissions de traverser les dossiers parents.
Vérifier que personne n’a ouvert le fichier en écriture avant.

 

Tout simplement avec un except IOError, OSError

 

Du coup je reste perdu... Je ne sais pas quoi privilégier et qu'elle est la façon normale de procéder.

 

Egalement, pourquoi créer soit même une exception (raise) pour la traiter ensuite, alors qu'on peut la traiter desuite ?


Message édité par Tempus_Fugit le 28-01-2015 à 19:03:17
Reply

Marsh Posté le 28-01-2015 à 18:37:58   

Reply

Marsh Posté le 30-01-2015 à 15:17:35    

up

Reply

Marsh Posté le 30-01-2015 à 16:44:19    

La question m’intéresse aussi, histoire d'optimiser un peu mon code :)
 
Pour l'instant je me contente d'un :
 

Code :
  1. def loadListTxt(self, p_filename, p_except_exit = True) :
  2.         """ Fonction qui charge un fichier txt
  3.             et renvoi la liste des roms """
  4.         try:
  5.             fichier = open(p_filename,'r')
  6.         except IOError as err :
  7.             self.printLog("ERROR : Impossible de charger le fichier : {1} \n\n {0}".format(err, p_filename))
  8.             if p_except_exit :
  9.                 exit()
  10.             roms_list = False
  11.         except:
  12.             self.printLog("ERROR : Unexpected error:", sys.exc_info()[0])
  13.             if p_except_exit :
  14.                 exit()
  15.             roms_list = False           
  16.         else :
  17.             self.printLog("Fichier {0} chargé".format(p_filename))       
  18.             roms_list = fichier.read()
  19.             roms_list = roms_list.split('\n')
  20.             fichier.close()
  21.         return roms_list


Message édité par ramax le 30-01-2015 à 16:58:24
Reply

Marsh Posté le 30-01-2015 à 16:46:47    

J'ai continué à potasser la question, à priori il n'y a rien de défini... Souvent on se passe des exceptions car il existe un raccourci ce qui rend le code moins verbeux...
 
Bref je trouve ça assez pompeux comme raison, contourner un système créer POUR, simplement pour que ce soit moins lourd. Ça me rappel le PHP.
 
Si un pro pouvait partageait son avis...

Reply

Marsh Posté le 30-01-2015 à 17:09:51    

Moi je ne passe pas des exceptions, puis comme tout mes chargement de fichier, que ce soit, text, xml, ou pickle, ils sont tous inclus dans des fonction je peux me permettre de faire des tests. Puis tu gagne un temps fou quand tu debug de savoir directement d’où provient le probleme
 
J'utilise aussi " os.path.exists " ainsi que isdir, ou isfile assez fréquemment. Quand j'importe un module perso qui traite des fichier XML je fais en premier des tests sur le "chemin/fichier"  
 
 

Code :
  1. # ²PATH==================================================================== =#
  2.     def testPath(self, p_emulurl, p_romslurl, p_except_exit = True) :
  3.         self.printLog('\n' + '='*65)
  4.         self.printLog("[PATH TEST]" ) 
  5.         if p_emulurl :
  6.             if os.path.exists(p_emulurl) and os.path.isfile(p_emulurl):
  7.                 self.emul_url = p_emulurl
  8.                 self.printLog("Chemin du .exe  OK : {0}".format(self.emul_url))
  9.             else :
  10.                 self.printLog("ERROR : Le chemin du .exe est incorrect : {0}".format(p_emulurl))
  11.                 self.is_error = True
  12.                 if p_except_exit :
  13.                     exit()
  14.         else :
  15.             self.printLog("ERROR : Le chemin du .exe est vide {0}".format(p_emulurl))
  16.             self.is_error = True
  17.             if p_except_exit :
  18.                     exit()
  19.                
  20.         if p_romslurl :
  21.             if os.path.exists(p_romslurl) and os.path.isdir(p_romslurl):
  22.                 self.roms_url = p_romslurl
  23.                 self.printLog("Chemin des roms OK : {0}".format(self.roms_url))
  24.             else :
  25.                 self.printLog("ERROR : Le chemin des roms est incorrect : {0}".format(p_romslurl))
  26.                 self.is_error = True
  27.                 if p_except_exit :
  28.                     exit()
  29.         else :
  30.             self.printLog("ERROR : Le chemin des roms est vide : {0}".format(p_emulurl))
  31.             self.is_error = True
  32.             if p_except_exit :
  33.                 exit()
  34.         self.printLog("   Please wait : Loading ..." )


 
 
puis lors du chargement du fichier j'utilise les exceptions


Message édité par ramax le 30-01-2015 à 17:17:34
Reply

Marsh Posté le 30-01-2015 à 17:19:19    

En fait pour répondre à ta question : Quand privilégier les exceptions ?
 
Je ne vois aucun intérêt à ne pas les utiliser.
 
Même quand j'importe des modules :  
 

Code :
  1. #============================================================================#
  2. #= ²RECQUIS================================================================ =#                                                         
  3. #============================================================================#
  4. # Import des modules Python
  5. try :
  6.     import sys
  7.     import subprocess
  8.     import os.path
  9.     import pickle
  10.     from PySide import QtCore, QtGui
  11. except ImportError as err :
  12.     input("ERROR : Impossible d'importer le module {0}".format(err))
  13.     exit()


Message édité par ramax le 30-01-2015 à 17:19:49
Reply

Marsh Posté le 30-01-2015 à 17:23:12    

C'est aussi ce que j'aurais fais. Mais je souhaite intégrer les exceptions dans mon travail. Du coup c'est surtout une question d'idéologie (c'est peut être pas le bon mot) plus que de pratique je trouve.
 
Je prends par exemple l'utilité clair de l'exception forms.ValidationError lors de la validation d'un formulaire Django.
Lever cette exception fait que django renvoi "tout seul" le formulaire, et il affiche "tout seul" où se trouve l'erreur, etc...
Vérification et renvoi qu'on peut très bien faire par soit même (comme tout en fait). Du coup c'est explicite que lever l'exception est la bonne pratique dans ce cas.
 
Bref je ne sais donc toujours pas la philosophie des exceptions et leur place.
 
A la limite, comme tu l'as dis, on utilise l'exception et si on veut plus de précision on gère l'erreur soit même. Ce qui ferait que les exceptions ne seraient pas si utiles que ça (puisqu'on peut tout faire soit même). Je ne vois que ça

Reply

Marsh Posté le 31-01-2015 à 17:08:46    

Un avantage important dans certains cas, particulièrement pour les fichiers, c'est qu'en passant par
les exceptions tu évites d'avoir des problèmes si le fichier apparaît ou disparaît entre le moment où
tu testes son existence et le moment où tu l'ouvres.

 

C'est pas de bol quand ça arrive, la fenêtre de temps est petite, mais ça arrive et le résultat est assez
catastrophique si justement tu n'as aucun endroit pour attraper l'exception, ton programme s'arrête
ou ta page web renvoie une 500.

 

Après il faut l'attraper au bon endroit, pas forcément exactement là où elle apparaît, plutôt là où tu
peux la traiter: réessayer, afficher un message d'erreur, annuler l'effet des opérations à moitié
commencées, traduire l'exception par une autre de plus haut niveau.

 

Par exemple: un fichier python est absent ou a une erreur de syntaxe, ça correspond à au moins
deux exceptions différentes, mais le bout de code qui s'occupe d'importer les modules python les
attrape et les englobe dans un ImportError avec un message explicatif, parce que ce qui compte pour
le mec qui importe des modules c'est de savoir si ça réussit ou pas, il a pas à savoir à l'avance les
250 causes possibles d'exception improbables, et prévoir 250 except différents, il attrape ImportError
et en cas de souci il peut lire le message ou la série d'exceptions qui a causé cette exception).

 

Pour le cas des fichiers, s'il y a de l'interface utilisateur, ça arrive aussi d'avoir le "if" *et* la gestion
d'exceptions, le "if" est utilisé pour dire à l'utilisateur qu'il s'est planté dans son chemin de fichier
et qu'il faut qu'il le change, alors que la gestion d'exception est là pour la robustesse (par rapport
au cas expliqué au début). Par exemples dans certaines bases de code, en cas d'erreur à la lecture
d'un fichier, on va ré-essayer 2-3 fois de le ré-ouvrir avant d'échouer et de remonter l'erreur plus
haut, à cause des antivirus ou des générateurs de preview qui bloquent le fichier pendant un court
laps de temps, ça vaut le coup de patienter un peu. Après, tous les programmes n'ont pas forcément
besoin d'une telle robustesse, y'a souvent des trucs plus prioritaires à peaufiner avant.


Message édité par 0x90 le 31-01-2015 à 17:09:38

---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 01-02-2015 à 04:45:03    

Entre les styles EAFP et LBYL, je préfère le premier pour la raison qu'avec LBYL, le même test est fait deux fois: une fois dans ton code et une deuxième fois par l’implémentation de python.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed