Les exceptions avec Python 3

Comment gérer les exceptions et créer les siennes

a marqué ce sujet comme résolu.

Tout le monde se secoue ! :D

J’ai commencé (il y a 3 heures) la rédaction d’un tutoriel au doux nom de « Les exceptions avec Python 3 » et j’ai pour objectif de proposer en validation un texte aux petits oignons. Je fais donc appel à votre bonté sans limites pour dénicher le moindre pépin, que ce soit à propos du fond ou de la forme. Vous pourrez consulter la bêta à votre guise à l’adresse suivante :

A priori, le contenu est à peu près terminé. Je voulais faire quelque chose qui se lise rapidement et qui ne s’écarte pas trop du sujet. Cependant, j’ai l’impression que le contenu devrait être plus "aéré", qu’en pensez-vous ? Dois-je enlever quelques exemples de code ?

TODO :

  • Introduction
  • Conclusion
  • Logo
  • Ortho/typo

Merci !

+0 -0

Salut,

En effet, sans introduction le début de la lecture est pour le moment un peu brut. Aussi, je suis gêné par la première phrase, qui occulte que des levées d’exceptions peuvent être des situations tout à fait normales, et n’empêchent en rien le programme de continuer son exécution, l’exemple le plus flagrant étant StopIteration.

En parlant d’exemple, le premier que tu donnes n’est pas terrible puisque l’erreur de syntaxe qui survient n’est pas une exception (bien que SyntaxError soit une classe d’exception, ce n’est pas la même chose). Tu ne peux pas l’attraper par exemple.

Il y a quelques confusions dans le vocabulaire, comme quand tu parles de TypeError levée par une fonction et que l’exemple présente une addition, ou entre itérable et indexable même si le paragraphe se comprend globalement bien, ou encore dire qu’une classe « contiendrait » pass (c’est plus le bloc de définition qui contient le mot-clé).

Tous les codes présentés dans la première section sont dans l’interpréteur interactif, et tu expliques que les exceptions sont accessibles depuis le terminal. C’est bien, mais lever une exception se fait très rarement dans ce cas d’usage, donc ça fait un peu bizarre.

Je ne comprends pas trop le paragraphe sur les chaînes de formatage et sur le fait de modifier la chaîne.

Les exemples donnés gagneraient sûrement à refléter des problèmes de la vie réelle, plutôt que des cas d’école qui ne correspondent pas à grand chose.

Tu conseilles de ne pas abuser d’exceptions personnalisée par rapport à la réutilisation du code, mais justement, dans la réalisation d’une bibliothèque par exemple il est souvent bien plus facile d’avoir des exceptions qui héritent toutes d’une base commune pour pouvoir les filtrer plus ou moins finement, comme expliqué ici.

Au passage, toutes les exceptions n’héritent pas de la classe Exception, je t’invite à lire la page dont je donne le lien plus bas.

Je ne comprends pas ce que tu veux dire par «  il faut penser à ajouter un paramètre dédié et à appeler la méthode __init__ de Exception avec ce paramètre » ni à quel moment dans le code tu fais appel à la méthode de la classe parente.

Aussi, cela manque de liens vers des sources complémentaires, comme la hiérarchie des classes d’exception Python.

J’ai pas eu le temps de tout lire, néanmoins bien que les exceptions soient très pratiques je sais que niveau complexité/temps c’est vraiment affreux, je ne sais plus où j’avais lu ça mais je crois que par exemple en Java c’est vraiment pas opti. Dans d’autres langages comme OCaml apparement c’est justement beaucoup mieux mis en place, et donc les exceptions ne sont pas trop gourmandes (je ne sais pas par contre pourquoi techniquement c’est plus rapide en OCaml).

Je profite donc du thread pour demander si en Python les exceptions bien que très importantes sont gourmandes niveau temps ou pas ?

(Voilà j’espère que le thread est adapté et que je ne suis pas hors-sujet auquel cas je m’excuse).

Coucou, \o

J’ai rien à ajouter aux remarques de entwanne (si ce n’est qu’une conclusion, ce serait bien). Le tutoriel est cool.

Si ! Les mot-clés ne ressorte pas forcément super bien. Ce n’est que mon avis cependant. Facile à améliorer, ça doit valoir le coup.

+0 -0

Je profite donc du thread pour demander si en Python les exceptions bien que très importantes sont gourmandes niveau temps ou pas ?

À l’échelle de Python, le mécanisme n’a pas vraiment de grosse incidence sur le temps d’exécution d’un programme.

+1 -0

Salut,

Le lien de bas de page pour lark n’est pas correct.

+0 -0

Je profite donc du thread pour demander si en Python les exceptions bien que très importantes sont gourmandes niveau temps ou pas ?

À l’échelle de Python, le mécanisme n’a pas vraiment de grosse incidence sur le temps d’exécution d’un programme.

nohar

Et même, en python il y a l’adage "better ask forgiveness than permission". Les erreurs sont très rapides en python et il peut être plus rapide d’en générer que de vérifier qu’on ne va pas en lever. Un ami avait amélioré les perfs du logiciel de sa boîte en passant par les exceptions, une fois.

Sinon pour en revenir au contenu du tuto, pour moi il manque encore des trucs que j’utilise tous les jours.

except ... as ...: : (Edit: ah si, il y est)

1
2
3
4
5
try:
   # ...
   pass
except ValueError as err: 
   print("Something went wrong:", err)

raise ... from ...:

1
2
3
4
5
6
7
8
9
class MyError(Exception):
   pass

try:
   # ...
   pass
except ValueError as err: 
   # indique que err est la cause directe de MyError
   raise MyError("Something went wrong") from err

et raise sans argument

1
2
3
4
5
6
try:
    # ...
    pass
except (ValueError, RuntimeError) as err:
    print("Something went wrong:", err)
    raise  # Relance l'exception sans affecter son traceback
+1 -0

Merci pour vos retours !

Aussi, je suis gêné par la première phrase, qui occulte que des levées d’exceptions peuvent être des situations tout à fait normales, et n’empêchent en rien le programme de continuer son exécution, l’exemple le plus flagrant étant StopIteration.

En effet, mais du coup je ne vois pas trop comment formuler ça. C’est la première fois que je rédige un contenu sur le Python, peut-être ai-je un peu dépassé ma "limite pédagogique".

Il y a quelques confusions dans le vocabulaire, comme quand tu parles de TypeError levée par une fonction et que l’exemple présente une addition

N’est-ce pas la fonction (enfin la méthode) __add__ du type int qui lève cette exception (bien que ça puisse être confus, je vais modifier ça) ?

C’est bien, mais lever une exception se fait très rarement dans ce cas d’usage, donc ça fait un peu bizarre.

En effet, je voulais simplement qu’il n’y a pas besoin d’importer quelque chose pour lever une exception (elles sont dans les builtins). Et vu que le terminal permet d’essayer des petits bouts de code facilement, je me suis dit que ça en faisait un bon outil pour débuter.

Les exemples donnés gagneraient sûrement à refléter des problèmes de la vie réelle, plutôt que des cas d’école qui ne correspondent pas à grand chose.

Je vais être limité par mon expérience. À part dans des "gros" morceaux de code, je ne les utilise qu’occasionnellement.

Tu conseilles de ne pas abuser d’exceptions personnalisée par rapport à la réutilisation du code, mais justement, dans la réalisation d’une bibliothèque par exemple il est souvent bien plus facile d’avoir des exceptions qui héritent toutes d’une base commune pour pouvoir les filtrer plus ou moins finement, comme expliqué ici.

En effet, mais là je pensais plutôt aux exceptions comme TypeError. Si on créé un module qui fourni une fonction qui prend un int en paramètre et qu’on lui passe une str, il vaut mieux (à mon humble avis) lever une TypeError qu’une exception perso. En revanche, si le traitement du nombre passé en paramètre produit une erreur, alors en effet, une exception qui hérite d’une autre dédiée au module est plus adaptée.

Je ne comprends pas ce que tu veux dire par «  il faut penser à ajouter un paramètre dédié et à appeler la méthode init de Exception avec ce paramètre » ni à quel moment dans le code tu fais appel à la méthode de la classe parente.

En effet, petit oubli de ma part. Je corrige.


Bien vu nohar, je vais les rajouter.


J’ai été très pris ces derniers temps et je n’ai donc pas programmé depuis longtemps. Me lancer dans un mini-tuto sur le sujet était peut-être un peu présomptueux de ma part. Du coup, n’hésitez surtout pas à reprendre ce tuto si vous voulez faire quelque chose de votre côté ! ;)

+0 -0

En effet, mais du coup je ne vois pas trop comment formuler ça. C’est la première fois que je rédige un contenu sur le Python, peut-être ai-je un peu dépassé ma "limite pédagogique".

rezemika

Pour moi le plus simple serait de renverser la proposition, de dire qu’un cas anormal est signalé par une exception.

N’est-ce pas la fonction (enfin la méthode) __add__ du type int qui lève cette exception (bien que ça puisse être confus, je vais modifier ça) ?

rezemika

Techniquement c’est bien ce qu’il se passe, si, mais c’est implicite est ça ne transparaît pas quand on voit l’expression. Dire « opération » ou « expression » serait plus générique.

En effet, je voulais simplement qu’il n’y a pas besoin d’importer quelque chose pour lever une exception (elles sont dans les builtins). Et vu que le terminal permet d’essayer des petits bouts de code facilement, je me suis dit que ça en faisait un bon outil pour débuter.

rezemika

Je vois ce que tu veux dire mais je pense que tu gagnerais à présenter tes exemples les plus complexes comme des fichiers.

Je vais être limité par mon expérience. À part dans des "gros" morceaux de code, je ne les utilise qu’occasionnellement.

rezemika

Il y a pas mal de choses qui peuvent être faites avec IndexError ou KeyError, dans la manipulation de structures de données.

En effet, mais là je pensais plutôt aux exceptions comme TypeError. Si on créé un module qui fourni une fonction qui prend un int en paramètre et qu’on lui passe une str, il vaut mieux (à mon humble avis) lever une TypeError qu’une exception perso. En revanche, si le traitement du nombre passé en paramètre produit une erreur, alors en effet, une exception qui hérite d’une autre dédiée au module est plus adaptée.

rezemika

Combiner les deux n’est pas impossible. Je n’ai pas de cas précis en tête, mais on pourrait imaginer une exception héritant à la fois de MyLibError et ValueError. Pour TypeError c’est un peu plus tordu en effet.

J’ai été très pris ces derniers temps et je n’ai donc pas programmé depuis longtemps. Me lancer dans un mini-tuto sur le sujet était peut-être un peu présomptueux de ma part. Du coup, n’hésitez surtout pas à reprendre ce tuto si vous voulez faire quelque chose de votre côté ! ;)

rezemika

Présomptueux je ne pense pas, non, c’est globalement du bon travail pour un premier jet. Après on trouvera toujours quelques petites choses à redire. :p

Je n’ai pas trop le temps de relire la nouvelle version là, mais j’y jetterai un œil plus tard.

Bonjour les agrumes !

La bêta a été mise à jour et décante sa pulpe à l’adresse suivante :

Voici une seconde mise à jour ! J’ai ajouté une intro, enlevé les chevrons du terminal sur les gros exemples et corrigés quelques détails. Il me reste encore à rendre les exemples plus concrets.

Merci d’avance pour vos commentaires.

+0 -0

Bonjour les agrumes !

La bêta a été mise à jour et décante sa pulpe à l’adresse suivante :

Petite mise à jour avec quelques corrections typographiques. :)

Merci d’avance pour vos commentaires.

+0 -0

Hello,

Du nouveau du côté de ce contenu ?

+0 -0

Salut !

À vrai dire j’avais un peu oublié ce contenu. :honte:
Je vais essayer de trouver la motivation (et surtout le temps) de m’y remettre… :)

+0 -0

Je fais sûrement une remarque dans le vide vu l’inactivité du contenu, mais il serait intéressant de faire un apparté/une petite bulle d’info en fin concernant la création d’une nouvelle pile et de l’asynchrone en cas de création de try: except: et que c’est à éviter quand on veut conserver des performances. Ne serait ce que pour ceux utilisant Python3 et Pygame, et abusant un peu des try except dans les fonctions appelés à chaque tour de boucle principal.

Salut ! Désolé, j’ai pris beaucoup de distances avec ZdS, je n’ai pas avancé depuis… Je te remercie pour ton retour ! Cependant, je serais limité par mes propres connaissances en Python, puisque je n’ai presque jamais fait de programmation asynchrone, désolé. Je n’exclus pas de le continuer, mais je ne peux rien garantir quant à une date. Toutefois, si quelqu’un a envie de le reprendre, je peux l’ajouter comme auteur. :)

+0 -0

Ayant lu le tutoriel, je pense qu’il est complet et qu’il peut quitter sa version bêta. Et je crois que tu as mal compris mon message, en fait, le try: except: fait ceci (je résume grossièrement):

pile 1 : ….. …… pile 2 : try :..except…

Le problème, tu l’auras deviné, c’est que, niveau performances, créer une seconde pile, asynchrone à la première, quand la première est en pause, c’est un peu prendre le mauvais des deux cotés ':). D’où la nécessité de connaître ce défaut d’utilisation des exceptions ( présent dans tous les langages utilisant des exceptions que je connais, et sûrement tous/quasiment tous)

Ah ? D’après mes VDD, il y avait encore plusieurs petites choses à modifier…

Je vois ! Cependant, je ne suis pas sur que je saurais vraiment formuler cette infobulle. Si tu as envie de l’écrire, je peux tout à fait la rajouter. Vu que c’est un mécanisme que je ne connaissais pas, je ne suis pas sur d’être le mieux placé pour en parler (je vais tenter quelque chose hein, mais juste je doute du résultat ^^ ).

+0 -0

L’infobulle pourrait ressembler à : " Attention, il vaut mieux éviter l’utilisation des exceptions lorsque l’on à besoin d’optimiser les performances de son programmes, par exemple dans une boucle qui doit être rapide ( jeux vidéos…). En effet, un try except provoque la création d’un thread asynchrone, alors que le thread principale est en pause, ce qui, sur des labs de temps très court, est un gouffre à performance. En revanche, pour tout ce qui nécessite pas un temps de réponse se comptant de l’ordre du 10ème de seconde, les exceptions font très bien leur job ;)."

Qu’en penses tu ?

Nope. La formulation n’est pas correcte.

Une source serait carrément appréciable.

L’infobulle est écrite sur le même ton que ce message. Il faut adapté la formulation.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte