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 :

choix d'une exception


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 640
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 640
    Par défaut choix d'une exception
    Bonjour,

    je ne sais quelle exception choisir pour marquer la fin d'une liste afin d'exécuter une alternative au déroulement normal d'un code.

    je vous montre en gros :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def maFonc:
        for k,v in enumerate(list):
            if vraiFaux(k,v):
                return 'a','b'
            elif k+1 == len(list):
                raise <là je ne sais pas>('fin de liste')
     
    def main():
        try:
            a,b = maFonc()
        except <là je ne sais pas> as err:
            autreFonc(err)
     
    main()
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  2. #2
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 319
    Par défaut
    bonjour

    pas compris ce pseudo code ... (pas sûr que l'exception est déclenchée à la fin de l'énumération)

    Existe StopIteration qui indique que nous sommes à la fin du parcours d'un conteneur. Si on déborde de la liste c'est IndexError

    dans la doc, la liste des exceptions

    ps: Il est possible de créer sa propre exception, tu peux la créer à partir de n'importe quelle exception déjà existante

    exemple
    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
    class FinDeBoucle(StopIteration):
        pass
     
    class ErreurDansBoucle(LookupError):
        def __init__(self, message, k=None):
            super().__init__(message)
            self.k = k if k else "?"
        def __str__(self):
            return f"{' '.join(self.args)} Erreur dans boucle, à l'index: {self.k}"
    #...
     
    try:
        raise ErreurDansBoucle("Opps", 18)
    except ErreurDansBoucle as err:
        print(err)
     
    raise FinDeBoucle()

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 816
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 816
    Billets dans le blog
    1
    Par défaut
    Bonjour
    A la base de ce qui va amener ton exception, tu vérifies k+1 > len(list). Or ceci ne peut pas arriver.
    Si tu énumères ta liste (à laquelle tu devrais donner un autre nom que celui d'un type Python...), quand tu termines ta liste tu la termines donc "k" ne monte plus. Donc cette situation ne peut pas arriver, ce qui explique que tu ne trouves pas d'exception pour le cas.

    L'exception est faite pour gérer un truc qui ne devrait pas arriver mais qui arrive. Style j'ouvre un fichier, je m'attends à ce qu'il s'ouvre. Qu'il ne s'ouvre pas ne devrait pas arriver mais ça arrive (parce que trompé dans le nom, parce que pas le droit, parce que ça devrait être un fichier mais un crétin d'admin a créé un dossier à sa place, parce que...) donc exception.
    Ou alors je lis une bdd et paf, l'admin la ferme pour faire une maintenance => exception. Mais un truc qui ne peut pas arriver, s'il arrive ce n'est pas une exception, c'est juste une erreur de prog.

    Le fait qu'un traitement dans la boucle donne un résultat particulier (style vraifaux() renvoie faux) n'est pas une exception, c'est un résultat. Donc tu peux faire retourner à ta fonction une valeur particulière signifiant "j'ai eu un résultat particulier".
    Exemple
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def chercheQqChose(aiguille, meule):
    	for (i, v) in enumerate(meule):
    		if vraiFaux(v, aiguille):
    			return i
    	# for
    	return None
    # chercheQqChose()

    L'exception est faite pour traiter un évènement que tu ne peux pas maîtriser. Gérer une valeur retournée par une fonction c'est un évènement que tu peux maîtriser donc qui ne doit pas être mis dans une exception (ce qui t'évite aussi un try/except chez l'appelant). Et la liste des évènements non-maîtrisables pouvant arriver dans un code est assez bien exhaustivement regroupée dans les exceptions classiques de Python. Et si certaines librairies particulières peuvent amener des évènements "en plus", alors la librairie possède aussi ses exceptions dédiées (style psycopg2, librairie pour attaquer une bdd Postgres, possède ses propres exceptions pour détecter "bdd injoignable" ou "insertion échouée" ou autres).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 319
    Par défaut
    Personnellement l'exception ne me choque pas, mais plutôt le elif (que Sve@r a corrigé)

    Il m'arrive d'avoir ce type de structure dans main, par exemple
    - si une option passée en paramètre du script n'existe pas (sda8 : ExceptionPartitionInvalide, ...)
    - si on désire remonter de plus d'un niveau main() -> sous_main() -> maFonc() et on désire bien traiter dans main()

    EDIT
    Citation Envoyé par Sve@r Voir le message
    L'exception est faite pour gérer un truc qui ne devrait pas arriver
    ...
    L'exception est faite pour traiter un évènement que tu ne peux pas maîtriser
    Pas d'accord, dans de nombreux langages objet, c'est un mécanisme très utilisé dans la lib standard en comportement "normal" ! Même en python avec justement StopIteration qui se produit à chaque fois que nous faisons une boucle (for) sur un itérateur (déclenchée mais aussi traitée donc non visible par nous)

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 816
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 816
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par papajoker Voir le message
    Pas d'accord
    Bon. J'espérais une adhésion sans faille...
    Enfin ce que je voulais dire, c'est qu'une fonction qui renvoie vrai/faux n'a pas vraiment besoin de créer une exception pour que l'appelant puisse gérer son résultat.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 319
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    c'est qu'une fonction qui renvoie vrai/faux n'a pas vraiment besoin de créer une exception pour que l'appelant puisse gérer son résultat.
    J'acquiesce et en général, il ne faut pas en abuser

    mais, parfois, il est bon d'avoir un détail sur l'erreur alors que le résultat ne va pas le donner (Et si exception perso, alors encore plus d'infos)
    ps: et une exception permet de retourner toujours le bon type (si on type)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def valide_bidon(a, b) -> bool:
    """    ...
    peut déclencher les exceptions : xxxx, yyyy
    """
      if a < b:
         raise Exception("est trop petit")
      if a +10 > b:  # j'ai pas d'imagination
         raise ExceptionPerso("est trop grand", a+10)
      return true if calculmath(a, b) > pi else false    # je fais du toumic2.0 ... ne cherchez pas une logique
    # ok, ici on pouvait retourner par exemple -2 -1 0 1 pour se passer des exceptions, mais est pour moi beaucoup plus lourd

    Note: si une fonction peut déclencher des exceptions, alors le mettre dans la documentation

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    je ne sais quelle exception choisir pour marquer la fin d'une liste afin d'exécuter une alternative au déroulement normal d'un code.
    Ce que j'en comprends c'est que la fonction doit retourner le premier tuple a, b trouvé ou une exception si aucun (a, b) vérifie la condition vraiFaux. Cela signifie qu'on a terminé la boucle et qu'on écrira plutôt:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    def maFonc:
        for k,v in enumerate(list):
            if vraiFaux(k,v):
                return 'a','b'
        raise <là je ne sais pas>('fin de liste')
    Pour ce qui est de remplacer "<là je ne sais pas>", soit vous fabriquez votre propre exception soit vous utilisez une exception existante (EOFError? ValueError?...): pour l'utilisateur (qui lit le message d'erreur), le texte est aussi important que le libélé.

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

  8. #8
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 640
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 640
    Par défaut
    Citation Envoyé par wiztricks
    la fonction doit retourner le premier tuple a, b trouvé ou une exception si aucun (a, b) vérifie la condition vraiFaux
    c'est exactement ça.
    et je vais simplifier comme tu le montres.

    EOFError, ou ValueError, c'est égal pour annoncer la fin d'une liste ?

    quant à construire ma propre exception... vous avez la référence de la documentation à ce sujet sur le site ?
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 816
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 816
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    c'est exactement ça.
    et je vais simplifier comme tu le montres.
    Moi j'aurais renvoyé None. Mais c'est juste mon avis.

    Citation Envoyé par N_BaH Voir le message
    EOFError, ou ValueError, c'est égal pour annoncer la fin d'une liste ?
    • EOF=End Of File => fin de fichier
    • ValueError: erreur de valeur, style tu cherches à convertir "toto" en int => ValueError

    Après, tout n'est question que de convention entre ta fonction et son appelant. T'as donc parfaitement le droit d'utiliser ZeroDivisionError si ça t'arrange. Mais pourquoi ne pas utiliser StopIteration mentionné par papajoker et qui est justement l'exception qui arrive quand on cherche à itérer trop loin dans un itérable?

    Citation Envoyé par N_BaH Voir le message
    quant à construire ma propre exception... vous avez la référence de la documentation à ce sujet sur le site ?
    https://tahe.developpez.com/tutoriel...les-exceptions paragraphe 5-3 mais il est un peu light. Sinon tape "python créer ses exceptions" dans ton moteur de recherche et tu auras plein d'infos...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 640
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 640
    Par défaut
    avant, je retournais False, mais j'avais une erreur can't unpack... pour laquelle, sur le net est préconisé de lever une exception; et me voilà!
    j'aurais pu faire return False,False, ou return None,None, mais je me suis dit qu'il allait falloir que je teste les valeurs du tuple, alors qu'avec une exception c'était direct.

    StopIteration je l'ai zappée, désolé. mais oui, bien sûr. tout simplement.

    merci à tous !
    j'ai de la lecture.

    je repasse clore dès que j'observe que ça fonctionne bien : je n'atteins pas la fin de la liste à chaque exécution du code, heureusement !
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  11. #11
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 816
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 816
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    j'aurais pu faire return False,False, ou return None,None, mais je me suis dit qu'il allait falloir que je teste les valeurs du tuple, alors qu'avec une exception c'était direct.
    Et.. tu as tenté return () que tu aurais pu, chez l'appelant, détecter via un... oserais-je dire "tout aussi direct" if res:=maFonc(): (a, b)=res

    Oups... serions-nous en présence d'un problème XY...

    PS: avec le return False dont tu parles ça reste possible aussi => if res:=maFonc(): (a, b)=res mais retourner un tuple vide, considéré comme False, amène la fonction à retourner toujours la même nature d'élément (ie toujours un tuple)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  12. #12
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 319
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    avant, je retournais False, mais j'avais une erreur can't unpack... pour laquelle, sur le net est préconisé de lever une exception
    Donc, tu pouvais faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def truc(a, b):
        # for .... : return 4, 5
        return None
     
    try:
        x, y = truc(1, 2)
    except TypeError:
        print("oups, tout listé et rien trouvé de valide")
    Mais, OK, ce n'est propre (car tout sauf explicite) et il y a (petit) risque que cette exception masque une autre erreur que celle voulue ("petit" uniquement si ta fonction est hyper simple)
    Pourquoi pas, si nous n'avons pas peur du gros mal de crâne lorsque nous relisons notre code 3 mois plus tard

    Citation Envoyé par N_BaH Voir le message
    est préconisé de lever une exception
    "lever" c'est le except , pas de créer une exception. Lorsque nous avons une exception (TypeError ici), OUI, il est préconisé de la lever (si nous savons la gérer). Nous ne savons pas la gérer ? Alors il ne faut surtout pas la lever et laisser notre script planter

  13. #13
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    EOFError, ou ValueError, c'est égal pour annoncer la fin d'une liste ?
    N'oubliez pas qu'il y a 3 "dimensions":
    • signaler bruyamment à l'appelant l'incapacité à retourner le tuple attendu (et le forcer à tester le retour explicitement avant de l'utiliser),
    • le type de l'exception (EOFError, ou ValueError): c'est ce qui va permettre à l'appelant de "filtrer" au cas il y a lieu de gérer l'exception,
    • le message qui va avec: c'est pour l'utilisateur.

    Si on documente les exceptions que l'exécution de la fonction pourrait lever et qu'on est sur que ce que la fonction consomme pourrait lever la même exception par ailleurs (une ambiguïté sur la cause sera plus difficile à gérer).
    Le problème est que les exceptions standards sont déjà documentées et qu'il n'est pas très futé de les utiliser pour des cas de figures qui n'ont rien à voir (puisqu'on peut créer ses exceptions!).

    Lisez la documentation de StopIteration et vous comprendrez qu'on ne peut pas utiliser ce type là ici!

    Citation Envoyé par N_BaH Voir le message
    quant à construire ma propre exception... vous avez la référence de la documentation à ce sujet sur le site ?
    Vous savez programmer, vous pouvez donc vous inspirez du tuto qui est livré avec Python. Il comprend un chapitre entier sur les exceptions qui aborde aussi comment les fabriquer (et c'est pas si compliqué: il suffit de sous/classer Exception!)

    - 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. erreur :"une exception s'est produite"
    Par leborg dans le forum ASP
    Réponses: 11
    Dernier message: 02/03/2004, 15h09
  2. [JSP] Affichage numéro de ligne d'une exception
    Par PhoneKilleR dans le forum Servlets/JSP
    Réponses: 12
    Dernier message: 23/09/2003, 14h59
  3. Réponses: 2
    Dernier message: 28/08/2003, 00h00
  4. Réponses: 3
    Dernier message: 01/11/2002, 14h30
  5. String Grid et choix d'une couleur pour une ligne
    Par Gigottine dans le forum C++Builder
    Réponses: 12
    Dernier message: 17/05/2002, 15h23

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