{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "< [Fichier I/O](PythonIntroCh9_FR.ipynb) | [Contenu](PythonIntro_FR.ipynb) >" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 10. Gestion des exceptions\n", "## 10.1 Introduction\n", "Si vous ne les avez jamais vus auparavant, c’est que vous n’essayez pas assez fort. Que sont-ils ? Erreurs. Exceptions. Problèmes. Vous savez de quoi je parle? Je l’ai eu avec ce programme:
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def menu(list, question):\n", " for entry in list:\n", " print(1 + list.index(entry),end=\"\")\n", " print(\") \" + entry)\n", "\n", " return input(question) - 1\n", "\n", "# exécution de la fonction \n", "# rappelez-vous ce que fait la barre oblique inverse\n", "\n", "answer = menu(['A','B','C','D','E','F','H','I'],\\\n", "'Which letter is your favourite? ')\n", "\n", "print('You picked answer ' + str(answer + 1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ceci est juste un exemple du programme de menu que nous avons fait plus tôt. Cela me semble parfaitement bien. Du moins jusqu’au moment où je l’ai essayé pour la première fois. Exécutez le programme et que se passe-t-il ?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 10.2 Bugs - Erreurs Humaines\n", "Les problèmes les plus courants avec votre code sont de votre propre fait. Triste, mais vrai. Que voyons-nous lorsque nous essayons d’exécuter notre programme handicapé?\n", "```Python\n", "---------------------------------------------------------------------------\n", "TypeError Traceback (most recent call last)\n", " in ()\n", " 8 # exécuter la fonction\n", " 9 # rappelez-vous ce que fait la barre oblique inverse\n", "---> 10 answer = menu(['A','B','C','D','E','F','H','I'],'Which letter is your favourite? ')\n", " 11 \n", " 12 print('You picked answer ' + str(answer + 1))\n", "\n", " in menu(list, question)\n", " 4 print(\") \" + entry)\n", " 5 \n", "----> 6 return input(question) - 1\n", " 7 \n", " 8 # exécuter la fonction\n", "\n", "TypeError: unsupported operand type(s) for -: 'str' and 'int'\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dites quoi? Ce que Python essaie de vous dire (mais qui a du mal à trouver un bon mot pour cela), c’est que vous ne pouvez pas joindre une chaîne de lettres et un nombre en une seule chaîne de texte. Passons en revue le message d’erreur et voyons comment il nous indique que: \n", "* `--->` montre les lignes où l’erreur est détectée. Vous pouvez voir qu’il pointe d’abord la ligne 10 (la chaîne), puis la ligne 6 (le calcul où nous soustrayons un entier d’une chaîne). Notez que la ligne 6 était dans la fonction. \n", "* `TypeError: type(s) d’opérande non pris en charge pour -: 'str' et 'int` vous indique l’erreur. Dans ce cas, il s’agit d’un 'TypeError', où vous avez essayé de soustraire des variables incompatibles " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il existe plusieurs listes de fichiers et de codes pour une seule erreur, car l’erreur s’est produite avec l’interaction de deux lignes de code (par exemple, lors de l’utilisation d’une fonction, l’erreur s’est produite sur la ligne où la fonction a été appelée, ET la ligne dans la fonction où les choses se sont mal passées.\n", "\n", "Maintenant que nous savons quel est le problème, comment pouvons-nous le résoudre. Eh bien, le message d’erreur a isolé où se trouve le problème, nous allons donc nous concentrer uniquement sur ce bout de code.\n", "```Python\n", "answer = menu(['A','B','C','D','E','F','H','I'],\\\n", "'Which letter is your favourite? ')\n", "```\n", "Il s’agit d’un appel à une fonction. L’erreur s’est produite dans la fonction dans la ligne suivante :\n", "```Python\n", " return input(question) - 1\n", "```\n", "`input` retourne toujours une chaîne, d’où notre problème. Changeons-le en `eval(input())`, qui, lorsque vous tapez un nombre, renvoie un nombre:\n", "```Python\n", " return eval(input(question)) - 1\n", "```\n", "Bug fixé!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 10.3 Exceptions - Limites du Code\n", "OK, le programme fonctionne lorsque vous faites quelque chose de normal. Mais que se passe-t-il si vous essayez quelque chose de bizarre? Tapez une lettre (disons, 'm') au lieu d’un nombre? Whoops!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def menu(list, question):\n", " for entry in list:\n", " print(1 + list.index(entry),end=\"\")\n", " print(\") \" + entry)\n", "\n", " return eval(input(question)) - 1\n", "\n", "# exécutez la fonction\n", "# rappelez-vous ce que fait la barre oblique inverse\n", "answer = menu(['A','B','C','D','E','F','H','I'],\\\n", "'Which letter is your favourite? ')\n", "\n", "print('You picked answer ' + str(answer + 1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Une erreur se produit dans la ligne 10 et l’autre dans la ligne 6. Ce que cela nous dit, c’est que lorsque nous avons appelé la fonction de menu à la ligne 10, une erreur s’est produite à la ligne 6 (où nous enlevons 1). Cela a du sens si vous savez ce que fait la fonction `input()` - j’ai fait un peu de lecture et de test, et j’ai réalisé que si vous tapez une lettre ou un mot, cela supposera que vous mentionnez une variable! donc à la ligne 6, nous essayons d’enlever 1 de la variable 'm', qui n’existe pas.
\n", "\n", "Vous n’avez aucune idée de la façon de résoudre ce problème? L’un des moyens les meilleurs et les plus simples est d’utiliser les opérateurs `try` et `except`.
\n", "\n", "Voici un exemple d’utilisation de `try` dans un programme:\n", "```Python\n", "try:\n", " function(world,parameters)\n", "except:\n", " print(world.errormsg)\n", "```\n", "C’est un exemple d’un petit bout de code vraiment désordonné que j’essayais de corriger. Tout d’abord, le code sous `try: ` est exécuté. En cas d’erreur, le compilateur accède à la section d’exception et imprime `world.errormsg`. Le programme ne s’arrête pas là et se bloque, il exécute le code sous `except: ` puis continue.
\n", "\n", "Essayons cela là où l’erreur s’est produite dans notre code (ligne 6). La fonction de menu est maintenant:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def menu(list, question):\n", " for entry in list:\n", " print(1 + list.index(entry),end=\"\")\n", " print(\") \" + entry)\n", " try:\n", " return eval(input(question)) - 1\n", " except NameError:\n", " print(\"Enter a correct number\")\n", "\n", "# exécuter la fonction\n", "# rappelez-vous ce que fait la barre oblique inverse\n", "answer = menu(['A','B','C','D','E','F','H','I'],\\\n", "'Which letter is your favourite? ')\n", "\n", "print('You picked answer ' + str(answer + 1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Essayez d’entrer une lettre lorsqu’on vous demande un numéro et voyez ce qui se passe. Dang. Nous avons résolu un problème, mais maintenant il a causé un autre problème plus loin sur la piste. Cela arrive tout le temps. (Parfois, vous finissez par tourner en rond, car votre code est un gâchis absolu). Jetons un coup d’œil à l’erreur.
\n", "\n", "Ce qui s’est passé cette fois-ci, c’est que la fonction de menu n’a renvoyé aucune valeur - elle a seulement imprimé un message d’erreur. Lorsqu’à la fin du programme, nous essayons d’imprimer la valeur retournée plus 1, quelle est la valeur retournée ? Il n’y a pas de valeur retournée ? Alors, qu’est-ce que 1 + ... eh bien, nous n’avons aucune idée de ce à quoi nous ajoutons 1!
\n", "\n", "Nous pourrions simplement retourner n’importe quel ancien chiffre, mais ce serait mentir. Ce que nous devrions vraiment faire, c’est réécrire le programme pour faire face à cette exception. Avec quoi? `try` and `except`!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def menu(list, question):\n", " for entry in list:\n", " print(1 + list.index(entry),end=\"\")\n", " print(\") \" + entry)\n", " try:\n", " return eval(input(question)) - 1\n", " except NameError:\n", " print(\"Enter a correct number\")\n", "\n", "answer = menu(['A','B','C','D','E','F','H','I'],\\\n", "'Which letter is your favourite? ')\n", "try:\n", " print(\"You picked answer\", (answer + 1))\n", "# vous pouvez mettre des trucs après une virgule dans la déclaration 'print', \n", "# et cela continuera comme si vous aviez tapé 'print' à nouveau\n", "except:\n", " print(\"\\nIncorrect answer.\")\n", "# le '\\n’est pour des raisons de mise en forme. Essayez sans elle et voir." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Problème encore résolu.\n", "## 10.4 Erreurs sans fin\n", "L’approche que nous avons utilisée ci-dessus n’est pas recommandée. Pourquoi? Parce qu’en dehors de l’erreur que nous savons peut se produire, `except: `attrape également toutes les autres erreurs. Que se passe-t-il si cela signifie que nous ne voyons jamais une erreur qui pourrait causer des problèmes sur les lignes de code? Si `except:` attrape chaque erreur sous le soleil, nous n’avons aucun espoir de contrôler les erreurs que nous traitons, et les autres que nous voulons voir, parce que jusqu’à présent, nous ne les avons pas traitées. Nous avons également peu d’espoir de traiter plus d’un type d’erreur dans le même bloc de code. Que faut-il faire, quand tout est désespéré ? Voici un exemple de code avec une telle situation : " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Subtraction program, v0.0.1 (beta)\")\n", "a = eval(input('Enter a number to subtract from > '))\n", "b = eval(input('Enter the number to subtract > '))\n", "print(a - b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, vous entrez vos deux nombres et cela fonctionne. Entrez une lettre, et il vous donne un `NameError`. Réécrivons le code pour traiter une `NameError` uniquement. Nous allons mettre le programme dans une boucle, afin qu’il redémarre si une erreur se produit (en utilisant `continue`, qui redémarre la boucle par le haut, et `break`, qui quitte la boucle):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Subtraction program, v0.0.2 (beta)\")\n", "loop = 1\n", "while loop == 1:\n", " try:\n", " a = eval(input('Enter a number to subtract from > '))\n", " b = eval(input('Enter the number to subtract > '))\n", " except NameError:\n", " print(\"\\nYou cannot subtract a letter\")\n", " continue\n", " print(a - b)\n", " try:\n", " loop = eval(input('Press 1 to try again > '))\n", " except NameError:\n", " loop = 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ici, nous avons redémarré la boucle si vous avez tapé quelque chose de mal. À la ligne 12, nous avons supposé que vous vouliez quitter le programme si vous n’appuyiez pas sur 1, nous avons donc quitté le programme.
\n", "\n", "Mais il y a encore des problèmes. Si nous laissons quelque chose en blanc, ou tapez un caractère inhabituel comme ! ou ;, le programme nous donne une `SyntaxError`. Traitons cela. Lorsque nous demandons que les chiffres soient soustraits, nous donnons un message d’erreur différent. Lorsque nous demandons d’appuyer sur 1, nous supposerons à nouveau que l’utilisateur souhaite quitter. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Subtraction program, v0.0.2 (beta)\")\n", "loop = 1\n", "while loop == 1:\n", " try:\n", " a = eval(input('Enter a number to subtract from > '))\n", " b = eval(input('Enter the number to subtract > '))\n", " except NameError:\n", " print(\"\\nYou cannot subtract a letter\")\n", " continue\n", " except SyntaxError:\n", " print(\"\\nPlease enter a number only.\")\n", " continue\n", " print(a - b)\n", " try:\n", " loop = eval(input('Press 1 to try again > '))\n", " except (NameError,SyntaxError):\n", " loop = 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comme vous pouvez le voir, vous pouvez avoir plusieurs utilisations de except, chacune traitant d’un problème différent. Vous pouvez également avoir un except pour faire face à plusieurs exceptions, en les mettant entre parenthèses et en les séparant par des virgules.
\n", "\n", "Maintenant, nous avons un programme qui est très difficile, à planter par un utilisateur final. Comme dernier défi, voyez si vous pouvez le planter. Il y a une façon à laquelle j’ai pensé - si vous lisez attentivement le chapitre sur l’erreur humaine, vous savez peut-être ce que c’est.\n", "\n", "## 10.5 Conclusion, Douce Conclusion\n", "Et voilà! La dernière leçon sur Python! Enfin, nous avons terminé." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "< [Fichier I/O](PythonIntroCh9_FR.ipynb) | [Contenu](PythonIntro_FR.ipynb) >" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" } }, "nbformat": 4, "nbformat_minor": 2 }