
Le bloc finally : exécuter du code dans tous les cas
Découvrez le bloc 'finally' en Python, un mécanisme essentiel pour exécuter du code de nettoyage, qu'une exception soit levée ou non dans un bloc 'try'. Assurez la libération des ressources et la finalisation des opérations.
Qu'est-ce que le bloc finally ? Définition et rôle
Le bloc `finally` est un bloc de code optionnel qui peut être ajouté à une structure `try...except` en Python. Le code à l'intérieur du bloc `finally` est *toujours* exécuté, qu'une exception ait été levée ou non dans le bloc `try`, et qu'elle ait été gérée ou non par un bloc `except`.
Le rôle principal du bloc `finally` est de garantir qu'un certain code sera exécuté, quelles que soient les circonstances. Cela est particulièrement utile pour :
- Libérer des ressources (fermer des fichiers, fermer des connexions réseau, libérer de la mémoire, etc.).
- Effectuer des opérations de nettoyage.
- Finaliser des actions, même en cas d'erreur.
Même si une instruction `return`, `break`, ou `continue` est rencontrée dans le bloc `try` ou `except`, le bloc `finally` sera exécuté *avant* que le contrôle ne quitte la structure `try...except...finally`.
Syntaxe du bloc finally : après try et except
Le bloc `finally` est placé après les blocs `try` et `except` (et `else`, s'il y en a un).
Syntaxe :
try:
# Code susceptible de lever une exception
# ...
except ExceptionType:
# Code pour gérer l'exception
# ...
finally:
# Code à exécuter dans tous les cas (qu'il y ait eu une exception ou non)
# ...Le bloc de code indenté après `finally:` est le bloc `finally`. Il est toujours exécuté.
Exemple (simple) :
try:
x = 10 / 2 # Pas d'erreur
print("Résultat :", x)
except ZeroDivisionError:
print("Division par zéro !")
finally:
print("Ce message s'affiche toujours.")Résultat :
Résultat : 5.0
Ce message s'affiche toujours.Exemple (avec une exception) :
try:
x = 10 / 0 # Division par zéro !
print("Résultat :", x) # Cette ligne n'est pas exécutée
except ZeroDivisionError:
print("Division par zéro !")
finally:
print("Ce message s'affiche toujours.")Résultat :
Division par zéro !
Ce message s'affiche toujours.Dans les deux cas, le message "Ce message s'affiche toujours." est affiché, que la division par zéro se produise ou non.
Cas d'utilisation courant : fermeture de fichiers
Un cas d'utilisation courant et crucial du bloc `finally` est la fermeture de fichiers.
Lorsque vous ouvrez un fichier en Python, il est important de le fermer lorsque vous avez fini de l'utiliser, pour libérer les ressources système associées au fichier. Si vous ne fermez pas le fichier, cela peut entraîner des problèmes (fuites de ressources, données non écrites sur le disque, etc.).
Exemple (sans `finally`, *problématique*) :
fichier = open("mon_fichier.txt", "w")
try:
# Ecrire des données dans le fichier
fichier.write("Quelques données...")
# ... (d'autres opérations qui pourraient lever une exception) ...
except Exception:
print("Une erreur s'est produite.")
# fichier.close() # Problème : si une exception se produit AVANT cette ligne, le fichier ne sera pas fermé !Dans cet exemple, si une exception se produit *avant* l'appel à `fichier.close()`, le fichier ne sera pas fermé.
Exemple (avec `finally`, *correct*) :
fichier = None # Initialisation pour gérer le cas où l'ouverture échoue
try:
fichier = open("mon_fichier.txt", "w")
# Ecrire des données dans le fichier
fichier.write("Quelques données...")
# ... (d'autres opérations qui pourraient lever une exception) ...
except Exception:
print("Une erreur s'est produite.")
finally:
if fichier:
fichier.close() # Le fichier est TOUJOURS fermé, même en cas d'exceptionDans cet exemple, le bloc `finally` garantit que le fichier sera fermé, qu'une exception se produise ou non dans le bloc `try`.
Notez qu'il existe une manière encore plus propre de gérer les fichiers en Python, en utilisant l'instruction `with` (voir la section sur les gestionnaires de contexte).
finally et return/break/continue
Même si une instruction `return`, `break`, ou `continue` est rencontrée dans le bloc `try` ou dans un bloc `except`, le bloc `finally` sera *toujours* exécuté avant que le contrôle ne quitte la structure `try...except...finally`.
Exemple :
def fonction_test():
try:
print("Dans le try")
return "Valeur du try"
except:
print("Dans l'except")
return "Valeur de l'except"
finally:
print("Dans le finally")
resultat = fonction_test()
print("Résultat :", resultat)
#Affiche:
#Dans le try
#Dans le finally
#Résultat : Valeur du tryDans cet exemple, bien que `return "Valeur du try"` soit exécuté dans le bloc `try`, le bloc `finally` est exécuté *avant* que la fonction ne retourne réellement la valeur. Cependant, la valeur retournée est bien celle du `return` du bloc `try`.
Si le bloc `finally` lui-même contient une instruction `return`, c'est la valeur retournée par le `finally` qui sera la valeur de retour de la fonction, *écrasant* toute valeur de retour précédente du `try` ou de l'`except`.
finally et les gestionnaires de contexte (with)
Le bloc `finally` est souvent utilisé pour garantir la libération de ressources, comme la fermeture de fichiers. Cependant, Python offre un moyen plus élégant et plus sûr de gérer ce type de situation : les gestionnaires de contexte, utilisés avec l'instruction `with`.
L'instruction `with` garantit que certaines opérations (comme l'ouverture et la fermeture d'un fichier) sont effectuées par paires, même en cas d'exceptions.
Exemple (avec `with` pour ouvrir et fermer un fichier) :
with open("mon_fichier.txt", "w") as fichier:
# Ecrire des données dans le fichier
fichier.write("Quelques données...")
# ... (d'autres opérations qui pourraient lever une exception) ...
# Le fichier est automatiquement fermé ici, même en cas d'exception à l'intérieur du bloc withL'instruction `with` est généralement préférable à l'utilisation explicite de `try...finally` pour la gestion des ressources, car elle est plus concise et moins sujette aux erreurs.
Cependant, le bloc `finally` reste utile dans d'autres situations où vous devez garantir l'exécution d'un bloc de code, quelles que soient les circonstances.