ajout de la doc sur les exceptions
This commit is contained in:
parent
03d5f17f6a
commit
03da3c99a0
|
@ -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 "<stdin>", line 1, in <module>
|
||||
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
|
|
@ -1,5 +1,7 @@
|
|||
Liste des exercices
|
||||
--------------------
|
||||
|
||||
.. todolist::
|
||||
Voici la liste des liens vers les différents exercices de la formation.
|
||||
|
||||
|
||||
.. todolist::
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue