# Open new file to write
file = None
try:
file = open(filePath, 'w')
except IOError:
msg = ("Unable to create file on disk.")
file.close()
return
finally:
file.write("Hello World!")
file.close()
Le code ci-dessus est extrait d'une fonction. L'un des systèmes de l'utilisateur signale une erreur en ligne:
file.write("Hello World!")
erreur:
AttributeError: 'NoneType' object has no attribute 'write'
La question est la suivante: si python n’est pas parvenu à ouvrir un fichier donné, le bloc «sauf» s’exécute et doit renvoyer, mais le contrôle est transféré sur la ligne qui génère une erreur donnée. La valeur de la variable 'file' est 'None'.
Des pointeurs?
Vous ne devriez pas écrire dans le fichier dans le bloc finally
car les exceptions déclenchées ne seront pas interceptées par le bloc except
.
Le bloc except
s'exécute s'il existe une exception déclenchée par le bloc try. Le finally
block always exécute quoi qu'il arrive.
En outre, il ne devrait pas être nécessaire d’initialiser la variable file
à none
.
L'utilisation de return
dans le bloc except
n'ignorera pas le bloc finally
. Par nature, il ne peut pas être ignoré. C’est pourquoi vous souhaitez y insérer votre code de "nettoyage" (c’est-à-dire la fermeture de fichiers).
Donc, si vous voulez utiliser essayer: sauf: enfin, vous devriez faire quelque chose comme ceci:
try:
f = open("file", "w")
try:
f.write('Hello World!')
finally:
f.close()
except IOError:
print 'oops!'
Pour ce faire, utilisez l’énoncé with
:
try:
with open("output", "w") as outfile:
outfile.write('Hello World')
except IOError:
print 'oops!'
Si le fichier n'est pas ouvert, la ligne file = open(filePath, 'w')
échoue et rien n'est affecté à file
.
Ensuite, la clause except
s'exécute, mais rien n'est dans le fichier, donc file.close()
échoue.
La clause finally
est toujours exécutée, même s'il y a eu une exception. Et puisque file
est toujours None, vous obtenez une autre exception.
Vous voulez une clause else
au lieu de finally
pour les événements qui ne surviennent que s'il n'y a pas d'exception.
try:
file = open(filePath, 'w')
except IOError:
msg = "Unable to create file on disk."
return
else:
file.write("Hello World!")
file.close()
Pourquoi la else
? Les docs Python dire:
L’utilisation de la clause else est préférable à l’ajout de code supplémentaire à la clause try car elle évite d’attraper accidentellement une exception qui n’a pas été générée par le code protégé par l’instruction try ... except.
En d'autres termes, cela n'acceptera pas une IOError
parmi les appels write
ou close
. Ce qui est bien, car alors la raison n'aurait pas été «Impossible de créer un fichier sur le disque». Cela aurait été une erreur différente, une erreur pour laquelle votre code n'a pas été préparé. C'est une bonne idée de ne pas essayer de gérer de telles erreurs.
Voici la solution la plus directe à votre problème. J'utilise l'idiome de la vérification de file_obj != None
dans le bloc finally
.
Soit dit en passant, vous devez savoir que file
est un nom de classe Python. Vous devez donc choisir un nom de variable différent.
file = None
try:
file = open(filePath, 'w')
except IOError:
msg = ("Unable to create file on disk.")
file.close()
return
finally:
if file != None:
file.write("Hello World!")
file.close()
sauf que ne s’exécute pas (car type est IOError), c’est la dernière partie qui génère une autre erreur de type AttributeError car file = None.
Vous pouvez faire quelque chose comme ça:
try:
do_some_stuff()
finally:
cleanup_stuff()
enfin, il est toujours appelé à la fin, même si une exception se produit. Vous pouvez vous en servir pour vous assurer que les ressources ouvertes sont fermées (par exemple, une connexion à une base de données, un fichier, etc.).
Je pense que vous avez mal compris la sémantique.
Votre logique doit être dans le "try", vous devez gérer les exceptions dans le bloc "except", et "finally" s'exécute quelle que soit la façon dont votre méthode se termine, utilisez-la pour nettoyer.