À ma honte, je ne peux pas comprendre comment gérer l'exception pour python 'avec' instruction. Si j'ai un code:
with open("a.txt") as f:
print f.readlines()
Je veux vraiment gérer "l'exception de fichier non trouvé" afin de faire quelque chose. Mais je ne peux pas écrire
with open("a.txt") as f:
print f.readlines()
except:
print 'oops'
et ne peut pas écrire
with open("a.txt") as f:
print f.readlines()
else:
print 'oops'
enfermer «avec» dans une instruction try / except ne fonctionne pas autrement: l'exception n'est pas déclenchée. Que puis-je faire pour traiter l'échec à l'intérieur de l'instruction 'with' de manière Pythonique?
python
exception-handling
grigoryvp
la source
la source
with
déclaration ne rompt pas comme par magie unetry...except
déclaration environnante .Réponses:
Si vous souhaitez une gestion différente des erreurs de l'appel ouvert par rapport au code de travail, vous pouvez le faire:
la source
try...except
blocs supplémentaires à l'intérieurwith
pour être plus proche de la source d'une exception qui n'a rien à voir avecopen()
.La meilleure façon "Pythonique" de faire cela, en exploitant l'
with
instruction, est répertoriée comme l'exemple # 6 dans PEP 343 , qui donne l'arrière-plan de l'instruction.Utilisé comme suit:
la source
try...except
instruction.L'instruction with est disponible sans
__future__
importation depuis Python 2.6 . Vous pouvez l'obtenir dès Python 2.5 (mais à ce stade, il est temps de mettre à niveau!) Avec:Voici ce que vous avez de plus proche à corriger. Vous y êtes presque, mais
with
vous n'avez pas deexcept
clause:La
__exit__
méthode d'un gestionnaire de contexte , s'il retourneFalse
, relancera l'erreur à la fin. S'il revientTrue
, il le supprimera. L'open
intégré__exit__
ne revient pasTrue
, il vous suffit donc de l'imbriquer dans un essai, à l'exception du bloc:Et passe-partout standard: n'utilisez pas un élément
except:
qui attrapeBaseException
et toutes les autres exceptions et avertissements possibles. Soyez au moins aussi précis queException
, et pour cette erreur, peut-être attraperIOError
. Ne détectez que les erreurs que vous êtes prêt à gérer.Donc dans ce cas, vous feriez:
la source
Différencier les origines possibles des exceptions soulevées à partir d'une
with
déclaration composéeLa
with
distinction entre les exceptions qui se produisent dans une instruction est délicate car elles peuvent provenir de différents endroits. Des exceptions peuvent être levées à partir de l'un des endroits suivants (ou des fonctions qui y sont appelées):ContextManager.__init__
ContextManager.__enter__
with
ContextManager.__exit__
Pour plus de détails, consultez la documentation sur les types de gestionnaire de contexte .
Si nous voulons faire la distinction entre ces différents cas, il ne suffit pas d' envelopper le
with
dans untry .. except
. Prenons l'exemple suivant (en utilisantValueError
comme exemple, mais bien sûr, il pourrait être remplacé par tout autre type d'exception):Ici, la
except
capture des exceptions provenant de chacun des quatre endroits différents et ne permet donc pas de les distinguer. Si nous déplaçons l'instanciation de l'objet gestionnaire de contexte en dehors dewith
, nous pouvons distinguer entre__init__
etBLOCK / __enter__ / __exit__
:En fait, cela a simplement aidé la
__init__
partie, mais nous pouvons ajouter une variable sentinelle supplémentaire pour vérifier si le corps de lawith
machine a commencé à s'exécuter (c'est-à-dire en faisant la différence entre__enter__
les autres):La partie délicate est de faire la différence entre les exceptions provenant de
BLOCK
et__exit__
parce qu'une exception qui échappe au corps duwith
sera transmise à__exit__
qui pourra décider comment la gérer (voir la documentation ). Si toutefois se__exit__
lève, l'exception d'origine sera remplacée par la nouvelle. Pour traiter ces cas, nous pouvons ajouter uneexcept
clause générale dans le corps de lawith
pour stocker toute exception potentielle qui aurait autrement échappé inaperçue et la comparer avec celle capturée le plus à l'extérieurexcept
plus tard - s'ils sont les mêmes, cela signifie que l'origine étaitBLOCK
ou__exit__
dans le cas contraire (dans le cas où il__exit__
supprime l'exception en renvoyant une valeur vraieexcept
ne sera tout simplement pas exécuté).Approche alternative utilisant le formulaire équivalent mentionné dans le PEP 343
PEP 343 - L'instruction "with" spécifie une version équivalente "non avec" de l'
with
instruction. Ici, nous pouvons facilement envelopper les différentes partiestry ... except
et ainsi différencier les différentes sources d'erreur potentielles:Habituellement, une approche plus simple fera très bien l'affaire
La nécessité d'une telle gestion des exceptions spéciales devrait être assez rare et normalement, le tout
with
dans untry ... except
bloc sera suffisant. Surtout si les diverses sources d'erreur sont indiquées par différents types d'exceptions (personnalisés) (les gestionnaires de contexte doivent être conçus en conséquence), nous pouvons facilement les distinguer. Par exemple:la source