Eu tenho uma função chamada pelo programa principal:
try:
someFunction()
except:
print "exception happened!"
mas, no meio da execução da função, gera exceção, e pula para a except
parte.
Como posso ver exatamente o que aconteceu no someFunction()
que causou a exceção?
except:
(sem o bareraise
), exceto talvez uma vez por programa e, de preferência, não o faça.except
cláusulas, não será necessário verificar o tipo de exceção, é o que geralmente é feito para agir de acordo com um tipo de exceção específico.except
Bloco interno: a exceção está disponível através dasys.exc_info()
função - Esta função retorna uma tupla de três valores que fornecem informações sobre a exceção que está sendo tratada no momento.Respostas:
As outras respostas apontam que você não deve capturar exceções genéricas, mas ninguém parece querer dizer o porquê, o que é essencial para entender quando você pode violar a "regra". Aqui está uma explicação. Basicamente, é para você não esconder:
Portanto, desde que você tome cuidado para não fazer nada disso, não há problema em capturar a exceção genérica. Por exemplo, você pode fornecer informações sobre a exceção ao usuário de outra maneira, como:
Então, como capturar a exceção genérica? Existem várias maneiras. Se você deseja apenas o objeto de exceção, faça o seguinte:
Certifique- se
message
de chamar a atenção do usuário de uma maneira difícil de perder! A impressão, como mostrado acima, pode não ser suficiente se a mensagem estiver oculta em muitas outras mensagens. Não chamar a atenção dos usuários é o mesmo que engolir todas as exceções, e se houver uma impressão que você deva ter depois de ler as respostas nesta página, é que isso não é uma coisa boa . Encerrar o bloco de exceção com umaraise
instrução solucionará o problema, re-levantando de maneira transparente a exceção que foi capturada.A diferença entre o exposto e o uso
except:
sem argumento é duplo:except:
não fornece o objeto de exceção para inspecionarSystemExit
,KeyboardInterrupt
eGeneratorExit
não são abrangidas pelo código acima, que é geralmente o que você quer. Veja a hierarquia de exceções .Se você também quiser o mesmo rastreamento de pilha que obtém se não capturar a exceção, poderá obtê-lo assim (ainda dentro da cláusula exceto):
Se você usar o
logging
módulo, poderá imprimir a exceção no log (junto com uma mensagem) assim:Se você quiser aprofundar e examinar a pilha, observe as variáveis etc., use a
post_mortem
função dopdb
módulo dentro do bloco de exceção:Eu achei esse último método inestimável ao caçar bugs.
fonte
Obtenha o nome da classe à qual o objeto de exceção pertence:
e usar a função print_exc () também imprimirá o rastreamento da pilha, que é uma informação essencial para qualquer mensagem de erro.
Como isso:
Você obterá uma saída como esta:
E após a impressão e análise, o código pode decidir não manipular exceções e apenas executar
raise
:Resultado:
E o intérprete imprime a exceção:
Após a
raise
exceção original, continua a se propagar ainda mais na pilha de chamadas. ( Cuidado com a possível armadilha ) Se você criar uma nova exceção, ela carrega um novo rastreamento (mais curto) da pilha.Resultado:
Observe como o traceback não inclui a
calculate()
função da linha9
que é a origem da exceção originale
.fonte
traceback.format_exc()
beme.__class__.__name__
é o mesmo quetype(e).__name__
, conforme sugerido pela resposta acima?Você geralmente não deve capturar todas as exceções possíveis,
try: ... except
pois isso é muito amplo. Basta pegar aqueles que se espera que aconteçam por qualquer motivo. Se você realmente precisar, por exemplo, se quiser descobrir mais sobre algum problema durante a depuração, façafonte
try: ... except Exception:
muitas coisas, por exemplo, o uso de bibliotecas dependentes da rede ou um massagista de dados que pode receber coisas estranhas enviadas a ela. Naturalmente, também tenho registro adequado. Isso é crucial para permitir que o programa continue operando no caso de um único erro nos dados de entrada.smtplib
?A menos que
somefunction
seja uma função legada codificada muito ruim, você não deve precisar do que está pedindo.Use várias
except
cláusulas para manipular de diferentes maneiras diferentes exceções:O ponto principal é que você não deve capturar exceções genéricas, mas apenas as que você precisa. Tenho certeza de que você não deseja ocultar erros ou bugs inesperados.
fonte
A maioria das respostas aponta para a
except (…) as (…):
sintaxe (com razão), mas ao mesmo tempo ninguém quer falar sobre um elefante na sala, onde o elefante estásys.exc_info()
funcionando. A partir da documentação do módulo sys (ênfase minha):Eu acho que isso
sys.exc_info()
poderia ser tratado como a resposta mais direta à pergunta original de Como sei que tipo de exceção ocorreu?fonte
except
. Apenas por uma questão de exaustividade,exctype, value = sys.exc_info()[:2]
mostrará o tipo de exceção que pode ser usado noexcept
.try: someFunction () exceto Exception, exc:
fonte
exc.__class__.__name__
já havia sido sugerido na resposta de Alex - stackoverflow.com/a/9824060/95735Essas respostas são adequadas para depuração, mas para testar programaticamente a exceção,
isinstance(e, SomeException)
pode ser útil, pois também testa subclassesSomeException
, para que você possa criar funcionalidades que se apliquem às hierarquias de exceções.fonte
Veja como estou lidando com minhas exceções. A idéia é tentar resolver o problema se isso for fácil e, posteriormente, adicionar uma solução mais desejável, se possível. Não resolva o problema no código que gera a exceção, ou esse código perde o controle do algoritmo original, que deve ser escrito diretamente. No entanto, passe os dados necessários para resolver o problema e retorne um lambda para o caso de você não conseguir resolver o problema fora do código que o gera.
Por enquanto, como não quero pensar tangencialmente no objetivo do meu aplicativo, não adicionei nenhuma solução complicada. Porém, no futuro, quando eu souber mais sobre possíveis soluções (já que o aplicativo foi projetado mais), eu poderia adicionar um dicionário de soluções indexadas por
during
.No exemplo mostrado, uma solução pode ser procurar dados de aplicativos armazenados em outro lugar, digamos se o arquivo 'app.p' foi excluído por engano.
Por enquanto, como escrever o manipulador de exceções não é uma ideia inteligente (ainda não sabemos as melhores maneiras de resolvê-lo, porque o design do aplicativo evoluirá), simplesmente retornamos a solução fácil que é agir como se estivéssemos executando o aplicativo pela primeira vez (neste caso).
fonte
Para adicionar à resposta de Lauritz, criei um decorador / wrapper para manipulação de exceções e os logs de wrapper cujo tipo de exceção ocorreu.
Isso pode ser chamado em um método de classe ou em uma função autônoma com o decorador:
@general_function_handler
Veja meu blog sobre para obter o exemplo completo: http://ryaneirwin.wordpress.com/2014/05/31/python-decorators-and-exception-handling/
fonte
Você pode começar como Lauritz recomendou, com:
e então apenas para
print ex
gostar assim:fonte
A exceção real pode ser capturada da seguinte maneira:
Você pode aprender mais sobre exceções no Tutorial do Python .
fonte
Sua pergunta é: "Como posso ver exatamente o que aconteceu no someFunction () que causou a exceção?"
Parece-me que você não está perguntando sobre como lidar com exceções imprevistas no código de produção (como muitas respostas assumidas), mas como descobrir o que está causando uma exceção específica durante o desenvolvimento.
A maneira mais fácil é usar um depurador que possa parar onde ocorre a exceção não capturada, de preferência não sair, para que você possa inspecionar as variáveis. Por exemplo, o PyDev no IDE de código aberto do Eclipse pode fazer isso. Para ativar isso no Eclipse, abra a perspectiva Debug, selecione
Manage Python Exception Breakpoints
noRun
menu e marqueSuspend on uncaught exceptions
.fonte
Evite capturar a exceção e o retorno que o Python imprime lhe dirá qual exceção ocorreu.
fonte