Para minha vergonha, não consigo descobrir como lidar com a exceção da instrução python 'with'. Se eu tiver um código:
with open("a.txt") as f:
print f.readlines()
Eu realmente quero lidar com 'arquivo não encontrado exceção' para fazer algo. Mas eu não sei escrever
with open("a.txt") as f:
print f.readlines()
except:
print 'oops'
e não pode escrever
with open("a.txt") as f:
print f.readlines()
else:
print 'oops'
incluir 'with' em uma instrução try / except não funciona mais: a exceção não é gerada. O que posso fazer para processar a falha dentro da declaração 'with' de uma maneira pitônica?
python
exception-handling
grigoryvp
fonte
fonte
with
declaração não magicamente quebra umatry...except
declaração circundante .Respostas:
Se você deseja um tratamento diferente para erros da chamada aberta versus o código de trabalho, você pode:
fonte
try...except
blocos extraswith
para ficar mais perto da fonte de uma exceção que não tem nada a veropen()
.A melhor maneira "Pythonic" de fazer isso, explorando a
with
declaração, é listada como Exemplo # 6 no PEP 343 , que fornece os antecedentes da declaração.Utilizado da seguinte forma:
fonte
try...except
declaração.A instrução with está disponível sem a
__future__
importação desde o Python 2.6 . Você pode obtê-lo já no Python 2.5 (mas, agora, é hora de atualizar!) Com:Aqui está a coisa mais próxima a ser corrigida. Você está quase lá, mas
with
não tem umaexcept
cláusula:O
__exit__
método de um gerenciador de contexto , se ele retornar,False
aumentará o erro ao concluir. Se retornarTrue
, ele será suprimido. Oopen
builtin__exit__
não retornaTrue
, então você só precisa aninhar em uma tentativa, exceto o bloco:E clichê padrão: não use nada
except:
que capteBaseException
e todas as outras exceções e avisos possíveis. Seja pelo menos tão específico quantoException
, e, para esse erro, talvez pegueIOError
. Capture apenas os erros que você está preparado para lidar.Portanto, neste caso, você faria:
fonte
Diferenciando entre as possíveis origens de exceções levantadas de uma
with
declaração compostaA diferenciação entre exceções que ocorrem em uma
with
instrução é complicada porque elas podem se originar em lugares diferentes. Exceções podem ser geradas a partir de um dos seguintes locais (ou funções aqui denominadas):ContextManager.__init__
ContextManager.__enter__
with
ContextManager.__exit__
Para mais detalhes, consulte a documentação sobre tipos de gerenciador de contexto .
Se quisermos distinguir entre esses casos diferentes, apenas agrupar o
with
em atry .. except
não é suficiente. Considere o seguinte exemplo (usandoValueError
como exemplo, mas é claro que poderia ser substituído por qualquer outro tipo de exceção):Aqui,
except
serão capturadas exceções originadas em todos os quatro locais diferentes e, portanto, não permitem distinguir entre eles. Se movermos a instanciação do objeto do gerenciador de contexto para fora dowith
, poderemos distinguir entre__init__
eBLOCK / __enter__ / __exit__
:Efetivamente, isso apenas ajudou na
__init__
parte, mas podemos adicionar uma variável sentinela extra para verificar se o corpo dowith
começou a executar (ou seja, diferenciar entre__enter__
os outros):A parte complicada é diferenciar as exceções originadas
BLOCK
e__exit__
porque uma exceção que escapa ao corpo dowith
será transmitida para__exit__
que possa decidir como lidar com isso (consulte os documentos ). Se, no entanto__exit__
, se elevar, a exceção original será substituída pela nova. Para lidar com esses casos, podemos adicionar umaexcept
cláusula geral no corpo dowith
arquivo para armazenar qualquer exceção em potencial que, de outra forma, passaria despercebida e compará-la com a capturada maisexcept
tarde no exterior - se forem iguais, significa que a origem foiBLOCK
ou de outra forma era__exit__
(no caso,__exit__
suprime a exceção retornando um valor verdadeiro o mais externoexcept
simplesmente não será executado).Abordagem alternativa usando o formulário equivalente mencionado no PEP 343
PEP 343 - A declaração "with" especifica uma versão equivalente "non-with" da
with
declaração. Aqui, podemos prontamente agrupar as várias partestry ... except
e, assim, diferenciar as diferentes fontes potenciais de erro:Geralmente, uma abordagem mais simples funciona muito bem
A necessidade desse tratamento de exceção especial deve ser bastante rara e normalmente envolver o todo
with
em umtry ... except
bloco será suficiente. Especialmente se as várias fontes de erro são indicadas por diferentes tipos de exceção (personalizados) (os gerenciadores de contexto precisam ser projetados de acordo), podemos distinguir facilmente entre elas. Por exemplo:fonte