247 lines
5.9 KiB
Plaintext
247 lines
5.9 KiB
Plaintext
.. 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
|