Dimitri Merejkowsky 5 лет назад
Родитель
Сommit
58497a3e34
1 измененных файлов: 133 добавлений и 45 удалений
  1. +133
    -45
      sessions/python-10.md

+ 133
- 45
sessions/python-10.md Просмотреть файл

@@ -5,16 +5,7 @@

\center \huge Exceptions

# Examples d'erreurs

* division par zéro
* dépassement d'un tableau
* clé non trouvée dans un dico
* opération entre types incompatibles
* le fichier n'existe pas
* la variable n'existe pas

# Les backtraces
# Exemple

```python
def une_fonction():
@@ -39,8 +30,9 @@ Traceback (most recent call last):
ZeroDivisionError: division by zero
```

ZeroDivisionError est une *classe*.

# Les backtraces
# Exemple modifié

```python
def une_fonction(diviseur):
@@ -52,7 +44,8 @@ def une_autre_fonction():
une_autre_fonction()
```

# Les backtraces
# Exemple modifié


```
Traceback (most recent call last):
@@ -65,16 +58,49 @@ Traceback (most recent call last):
ZeroDivisionError: division by zero
```

# Lever une exception
**Prenez le temps de lire les backtraces soigneusement!**


```python
def retirer_somme(compte, montant):
solde = ...
if montant >= solde:
raise ValueError("montant supérieur au solde!")
# Exemples d'erreurs

* `b += 2` - **NameError**
* `a / 9` - **ZeroDivisionError**
* `my_list[42]` - **IndexError**
* ``my_dict["bad-key"]`` - **KeyError**
* `1 + "two"` - **TypeError**
* `open("badpath")` - **FileNotFoundError**

# Hiérarchie d'exceptions (simplifiée)

```
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- Exception
+-- ArithmeticError
| +-- ZeroDivisionError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- OSError
| +-- FileNotFoundError
+-- TypeError
+-- ValueError

```

Liste complète dans la documentation:
https://docs.python.org/fr/3/library/exceptions.html#exception-hierarchy

# KeyboardInterrupt et SystemExit

* `KeyboardInterrupt` est levée quand on fait `ctrl-c`.

* `SystemExit` est levé quand on utilise `sys.exit()`
* Python cache la backtrace dans ce cas-là
* Pas utile de l'attrapper en général


# Attraper une exception

```python
@@ -85,16 +111,11 @@ except ZeroDivisionError:
print("someone tried to divide by zero!")
```

* Note: si l'exception n'est pas une fille de la classe attrapee, c'est rate.

# Attraper une exception

* On peut mettre plusieurs blocs de `except`
* On peut attraper plusieurs exceptions d'un coup

* Note: si l'exception n'est pas une fille de la classe attrapée, c'est raté.

# Attraper une exception

On peut mettre plusieurs blocs de `except`

```python
try:
@@ -105,43 +126,71 @@ except FileNotFoundError:
print("file not found")
```

# Attraper une exception

On peut attraper plusieurs exceptions d'un coup

Attention aux bare except
# Hiérarchies
À connaître
À utiliser si vous faites une librairie.
```python
try:
something_dangerous()
except (ZeroDivisionError, FileNotFoundError):
print("something bad happened")
```

# finally, else

# WBYL et EAFP

Watch Before You Leap
Easier to Ask for Forgiveness than Permission
```python
try:
something_dangerous()
except SomeError:
print("something bad happened")
else:
print("everything went well")
finally:
clean_up()
```

# WBYL

fichiers encore:
* Watch Before You Leap

```python
if exists():
if pas_un_dossier():
if j_ai_les_droits_en_lecture():
open(filename):
if pas_un_dossier():
if j_ai_les_droits_en_lecture():
open(filename):
```

# EAFP

* Easier to Ask for Forgiveness than Permission

```python
try:
open(filename):
file = open(filename)
catch IOError:
...
finally:
file.close()
```

# Avec with

Pas besoin de `finally` :)

# avec with
```python
try:
with file = open(filename):
lines = file.readlines()
except FileNotFoundError:
print("Fichier non trouvé")
```

L'exception est capturée, le fichier est fermé, puis l'exception est
levée à nouveau.

# attention a ou vous mettez except
# Attention à la position du except

```python
if truc:
@@ -150,6 +199,8 @@ if truc:
raise MyError("kaboom!")
````

# Attention à la position du except

```python
if truc:
if machin:
@@ -161,6 +212,7 @@ if truc:

```

# Attention à la position du except

```python
if truc:
@@ -173,9 +225,45 @@ if truc:

````

# Accédér aux détails de l'exception

* Avec `as`:

```python

try:
something_dangerous()
except FileNotFoundError as error:
print("file not found:", error.filename)
```

\vfill

# Accédér aux détails de l'exceptions
Voir la documentation pour les attributs disponibles.


# Lever une exception

* Avec raise

```python
def retirer_somme(compte, montant):
solde = ...
if montant >= solde:
raise ValueError("montant supérieur au solde!")
```

# Créer vos propres exceptions

Toujours hériter de `Exception`.

```python
class BankError(Exception):
....

class NotEnoughMoney(BankError):
def __init__(self, amount, withdrawal):
self.amount = amount
self.withdrawal = withdrawal
```

* Avec `as`
* Attrribut `args`
* Parfois d'autres atttributs (voir la doc)