From 03da3c99a06da3aca10e8fc5311157da78a29ec5 Mon Sep 17 00:00:00 2001 From: gwen Date: Mon, 4 May 2015 15:38:51 +0200 Subject: [PATCH] ajout de la doc sur les exceptions --- python/formation/exceptions.txt | 246 ++++++++++++++++++++++++++++ python/formation/exercices.txt | 4 +- python/formation/index.txt | 15 +- python/formation/structures.txt | 23 +-- python/formation/testsunitaires.txt | 33 +--- 5 files changed, 264 insertions(+), 57 deletions(-) create mode 100644 python/formation/exceptions.txt diff --git a/python/formation/exceptions.txt b/python/formation/exceptions.txt new file mode 100644 index 0000000..386413b --- /dev/null +++ b/python/formation/exceptions.txt @@ -0,0 +1,246 @@ +.. default-role:: literal + +Le style de programmation par exceptions +======================================== + +.. glossary:: + + Exception + + Les exceptions permettent de récupérer des situations où le calcul ne peut pas se poursuivre. + Dans ces cas, un récupérateur d'exceptions permet de continuer le calcul + sachant qu'une des branches a échoué. + + +Exemple d':term:`exception` + +>>> assert 2 == 1 +Traceback (most recent call last): + File "", line 1, in +AssertionError + + + +La règle du samouraï +---------------------- + +.. important:: règle du Samouraï : une fonction doit renvoyer le résultat escompté + ou bien lever une exception + + +>>> def function_raise(x): +... if not type(x) == int: +... raise TypeError("Pas le bon type") +... else: +... return x + 1 +... +>>> try: +... e = function_raise("une string") +... except TypeError, e: +... print e +... +Pas le bon type +>> + +- la fonction doit renvoyer des valeurs du même type (ou bien ``None``) +- la fonction doit lever une exception appropriée + + +utiliser la pile d'appel pour débugger +--------------------------------------- + +Utiliser la pile d'appels, elle se lit de bas en haut. Il est possible de +provoquer cette pile d'appels. + +:: + + import traceback + traceback.print_exc() + +.. todo:: s'exercer à lire une pile d'appels un peu complexe. + + +Traiter une exception avec + +:: + + try: + ... + except: + import traceback + traceback.print_exc() + + else: + bla bla + finally: + bla bla + +.. attention:: ne **jamais** briser la pile d'appels sans savoir précisément + ce que l'on fait, et remonter une autre exception + +Exemple : + + +>>> def function(x): +... if x == 1: raise TypeError("pas le bon type") +... else: return "ok" +... +>>> def function2(x): +... try: +... return "c'est " + function(x) +... except TypeError, e: +... raise AssertionError("on a une autre exception là") +... +>>> try: +... function2(1) +... except Exception, e: +... print e +... +on a une autre exception là +>>> + +Le raise (ou le re-raise) est souvent utilisé pour lever une exception métier +et cacher une exception système de bas niveau. + +exemple:: + + try: + add_s(dn, listdata) + except ldap.LDAPError, err: + raise MyOwnError(msg + str(err)) + except Exception: + pass + +.. todo:: dans quel cas entrons-nous dans le `else` ? dans le `finally` ? + +.. todo:: créer des exceptions métier + +exemple d'exceptions *dans la vraie vie*:: + + "user defined exceptions" + + + # Exceptions for an Option + class PropertiesOptionError(AttributeError): + "attempt to access to an option with a property that is not allowed" + def __init__(self, msg, proptype): + self.proptype = proptype + super(PropertiesOptionError, self).__init__(msg) + + + #____________________________________________________________ + # Exceptions for a Config + class ConfigError(Exception): + """attempt to change an option's owner without a value + or in case of `_cfgimpl_descr` is None + or if a calculation cannot be carried out""" + pass + + + class ContextError(Exception): + """context needed but not given + """ + pass + + + class ConflictError(Exception): + "duplicate options are present in a single config" + pass + + + #____________________________________________________________ + # miscellaneous exceptions + class RequirementError(Exception): + """a recursive loop occurs in the requirements tree + requires + """ + pass + + + class SlaveError(Exception): + "problem with a slave's value length" + pass + + + class ConstError(TypeError): + "no uniq value in _NameSpace" + pass + +Créer le plus possible ses propres exceptions spécifiques au programme +La programmation par exception peut vite devenir un style de programmation +très utilisé. C'est assez agréable mais le réserver pour la gestion d'une situation +particulière, que ça reste une intervention pour les cas non gérés par le programme +(en général). + +Les exceptions imbriquées +-------------------------------- + +>>> try: +... ma_func() +... except TypeError, e: +... do_something() +... except Exception, e: +... do_somethin_else() +... + +Exemple de programme utilisant massivement la programmation par exceptions : +`tiramisu`_ + +.. _tiramisu: http://tiramisu.labs.libre-entreprise.org/ + + +La hiérarchie des exceptions +----------------------------- + +Extrait de la documentation officielle:: + + BaseException + +-- SystemExit + +-- KeyboardInterrupt + +-- GeneratorExit + +-- Exception + +-- StopIteration + +-- StandardError + | +-- BufferError + | +-- ArithmeticError + | | +-- FloatingPointError + | | +-- OverflowError + | | +-- ZeroDivisionError + | +-- AssertionError + | +-- AttributeError + | +-- EnvironmentError + | | +-- IOError + | | +-- OSError + | | +-- WindowsError (Windows) + | | +-- VMSError (VMS) + | +-- EOFError + | +-- ImportError + | +-- LookupError + | | +-- IndexError + | | +-- KeyError + | +-- MemoryError + | +-- NameError + | | +-- UnboundLocalError + | +-- ReferenceError + | +-- RuntimeError + | | +-- NotImplementedError + | +-- SyntaxError + | | +-- IndentationError + | | +-- TabError + | +-- SystemError + | +-- TypeError + | +-- ValueError + | +-- UnicodeError + | +-- UnicodeDecodeError + | +-- UnicodeEncodeError + | +-- UnicodeTranslateError + +-- Warning + +-- DeprecationWarning + +-- PendingDeprecationWarning + +-- RuntimeWarning + +-- SyntaxWarning + +-- UserWarning + +-- FutureWarning + +-- ImportWarning + +-- UnicodeWarning + +-- BytesWarning diff --git a/python/formation/exercices.txt b/python/formation/exercices.txt index 2c5620d..6f5d8fa 100644 --- a/python/formation/exercices.txt +++ b/python/formation/exercices.txt @@ -1,5 +1,7 @@ Liste des exercices -------------------- -.. todolist:: +Voici la liste des liens vers les différents exercices de la formation. + +.. todolist:: diff --git a/python/formation/index.txt b/python/formation/index.txt index 5d779f9..dc1cf27 100644 --- a/python/formation/index.txt +++ b/python/formation/index.txt @@ -1,5 +1,5 @@ -apprentissage de la programmation avec python +Apprentissage de la programmation avec python ---------------------------------------------- .. toctree:: @@ -12,20 +12,29 @@ apprentissage de la programmation avec python testsunitaires -programmation python, connaissances de base +Programmation python, connaissances de base -------------------------------------------- + .. toctree:: :maxdepth: 1 classes prompt specialmethods + exceptions stdlib +Récapitulatifs de la formation +--------------------------------- + +.. toctree:: + :maxdepth: 1 + + exercices + Index et recherche ------------------- -* :doc:`exercices` * :ref:`genindex` * :ref:`modindex` * :ref:`search` diff --git a/python/formation/structures.txt b/python/formation/structures.txt index 060b8bf..0f8238a 100644 --- a/python/formation/structures.txt +++ b/python/formation/structures.txt @@ -1,3 +1,5 @@ +.. default-role:: literal + Structures de contrôle et fonctions ==================================== @@ -189,7 +191,6 @@ les expressions générateurs 18 >>> - le polymorphisme paramétrique ----------------------------- @@ -202,23 +203,3 @@ la fonction print 1 .. todo:: `print 1` et `print "1"` renvoient le même résultat. Pourquoi ? - -la programmation par exceptions -------------------------------------- - ->>> def function_raise(x): -... if not type(x) == int: -... raise TypeError("Pas le bon type") -... else: -... return x + 1 -... ->>> try: -... e = function_raise("une string") -... except TypeError, e: -... print e -... -Pas le bon type ->> - -.. important:: règle du Samouraï : une fonction doit renvoyer le résultat escompté - ou bien lever une exception diff --git a/python/formation/testsunitaires.txt b/python/formation/testsunitaires.txt index 42bdc32..061112f 100644 --- a/python/formation/testsunitaires.txt +++ b/python/formation/testsunitaires.txt @@ -19,7 +19,7 @@ les types de tests : Quel outil utiliser ? -- la :doc:`stdlib` propose le module :mod:`unittest` +- la :doc:`stdlib` propose le module :mod:`unittest` et unittest2. .. module:: py.test :synopsis: outil de test unitaires de la pylib @@ -66,37 +66,6 @@ options utiles dans `py.test` py.test -k test_simple - -utiliser la pile d'appel pour débugger ---------------------------------------- - -utiliser la pile d'appels, elle se lit de bas en haut. Il est possible de -provoquer cette pile d'appels. - -:: - - import traceback - traceback.print_exc() - - -traiter une exception avec - -:: - - try: - ... - except: - import traceback - traceback.print_exc() - - else: - bla bla - finally: - bla bla - - -créer le plus possible ses propres exceptions spécifiques au programme - utiliser le module :mod:`pdb` .. module:: pdb