f.close() en dernière ligne ressemble à une garantie. Ce n'est qu'un espoir.f.close() on the last line looks like a guarantee. It's only a hope.
Le Vol. VI a fermé sur une question de mémoire ; ce volume ouvre sur une question de nettoyage. Le numéro 08 a montré que la syntaxe de Python passe par des dunders ; with n'y échappe pas — ce numéro met au travail les siens, __enter__ et __exit__. Le réflexe le plus répandu pour fermer un fichier consiste à appeler close() en dernière ligne d'une fonction. Ce réflexe suppose, à tort, que le contrôle atteindra toujours cette ligne. Toute exception levée entre l'ouverture et cette dernière ligne saute directement par-dessus elle — le fichier reste ouvert, sans qu'aucune erreur ne le signale jamais.Vol. VI closed on a question of memory; this volume opens on a question of cleanup. Issue 08 showed that Python's syntax runs through dunders; with is no exception — this issue puts its own, __enter__ and __exit__, to work. The most common reflex for closing a file is calling close() on a function's last line. That reflex wrongly assumes control will always reach that line. Any exception raised between the opening and that last line jumps straight over it — the file stays open, with no error ever signaling it.
def traiter(chemin): f = open(chemin) donnees = f.read() resultat = 1 / len(donnees) # lève ZeroDivisionError si le fichier est vide f.close() # cette ligne ne s'exécute JAMAIS dans ce cas return resultat traiter("vide.txt") # ZeroDivisionError -- et le fichier reste ouvert, personne n'a appelé close()
Face à toute ressource ouverte — fichier, verrou, connexion — demande : ce nettoyage s'exécute-t-il seulement si tout se passe bien, ou même si une exception traverse le bloc ? S'il ne s'exécute que dans le premier cas, ce n'est pas une garantie.Facing any opened resource — file, lock, connection — ask: does this cleanup run only if everything goes well, or even if an exception crosses the block? If it only runs in the first case, it isn't a guarantee.
Le même problème touche un verrou (threading.Lock), une connexion réseau ou base de données, une transaction : toute ressource acquise puis censée être libérée par une dernière ligne de code, jamais garantie d'être atteinte.The same problem hits a lock (threading.Lock), a network or database connection, a transaction: any resource acquired and supposedly released by a final line of code, never guaranteed to be reached.