Sobre como capturar QUALQUER exceção


696

Como posso escrever um bloco try/ exceptque captura todas as exceções?


4
Na maioria dos casos, você provavelmente está fazendo algo errado se estiver tentando capturar alguma exceção. Quero dizer, você pode simplesmente digitar algo errado no código e nem saberá. É uma boa prática capturar exceções específicas.
precisa saber é o seguinte

12
Para ser mais preciso, capturar todas as exceções possíveis é apenas um problema se elas forem capturadas silenciosamente. É difícil pensar em onde mais essa abordagem é apropriada, além de onde as mensagens de erro capturadas são impressas sys.stderre possivelmente registradas. Essa é uma exceção perfeitamente válida e comum.
Evgeni Sergeev

você tentou try: whatever() except Exception as e: exp_capture() :?
Charlie Parker

Respostas:


564

Você pode, mas provavelmente não deveria:

try:
    do_something()
except:
    print "Caught it!"

No entanto, isso também trará exceções KeyboardInterrupte você geralmente não quer isso, não é? A menos que você apresente a exceção imediatamente, consulte o seguinte exemplo nos documentos :

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise


15
Sua última afirmação não é verdadeira; você precisa dizer explicitamente except Exception:o que está nu, exceto se você tiver lá também capturar os que são da BaseException.
Pykler 03/02

7
Você realmente deve imprimir em stderr.
precisa saber é o seguinte

41
Eu discordo muito fortemente da afirmação "não deveria". Você deve fazê-lo com moderação. Há momentos em que você lida com bibliotecas de terceiros (às vezes carregadas dinamicamente !!) que ficam totalmente loucas com exceções e rastrear todas elas pode ser uma tarefa muito dolorosa, e se você perder apenas uma, terá uma experiência muito enorme bug doloroso no seu sistema. Dito isto, é bom rastrear o máximo possível e manipulá-los adequadamente e, em seguida, ter uma captura de backup para todos os que você sentir falta.
Blaze

26
O que acho estranho também é que, em uma linguagem de digitação de pato, na qual você não declara variáveis ​​de instância, de repente se preocupa muito em não digitar todas as suas exceções. Hmm!
Chama

834

Além de uma except:cláusula simples (que, como outros já disseram que você não deve usar), você pode simplesmente capturar Exception:

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

Normalmente, você só consideraria fazer isso no nível mais externo do seu código se, por exemplo, quisesse lidar com exceções não capturadas antes de terminar.

A vantagem except Exceptionsobre o nu excepté que há algumas exceções que ele não vai pegar, mais obviamente KeyboardInterrupte SystemExit: se você pegou e engoliu os então você poderia torná-lo difícil para qualquer um sair do seu script.


Eu tinha a mesma coisa em mente, mas é uma desvantagem, suponha que sejam dois erros quando for detectado e, exceto se você estiver imprimindo, sairá do bloco try e nunca saberá o segundo erro. .

6
Para quem se pergunta, totalmente contrário à minha expectativa, isso ainda vai pegar subclasses sem exceção, como ints, pelo menos no python 2.x.
Joseph Garvin

5
@ Joseph Garvin, isso está incorreto, ou seja, isso não irá capturar "não-exceções" que não subclasses Exception. Observe que é impossível gerar uma intexceção e tentar fazer isso gera uma TypeErrorexceção, que é o que seria detectado pela except Exceptioncláusula anexa nesse caso. Por outro lado, uma classe de estilo antigo pode ser gerada e qualificada como uma "não exceção" que não subclasse Exception- isso será capturado por uma exceptcláusula simples , mas não por uma except Exceptioncláusula.
Yoel

4
@JosephGarvin verificar esta entrada de blog: chris-lamb.co.uk/posts/no-one-expects-string-literal-exception estou com @Yoel em um presente, o teste apenas mascarou aTypeError
Duncan

2
@CharlieParker nada de errado em pegá-los, se é isso que você quer, mas na maioria das vezes não. Ligar sys.exit()normalmente significa que você espera que o aplicativo seja encerrado, mas se você pegar o SystemExit, ele não será. Da mesma forma, se você pressionar Control-C em um script em execução (Ctrl-break no Windows), espera que o programa pare, para não pegar o erro e continuar. Mas você pode capturar um ou ambos, se quiser fazer a limpeza antes de existir.
Duncan

100

Você pode fazer isso para lidar com exceções gerais

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message

8
Isso pode não capturar todas as exceções, pois a classe base para todas as exceções é BaseException e eu encontrei um código de produção que não está na família de classes Exception. Veja docs.python.org/3/library/… para detalhes sobre isso.
DDay

4
Isso não captura todas as exceções.
Andy_A̷n̷d̷y̷

6
Tecnicamente, ele deve capturar todas as exceções que não saem do sistema. Dos documentos @DDay vinculados: " exceção BaseException: a classe base para todas as exceções internas. Não deve ser herdada diretamente pelas classes definidas pelo usuário (para isso, use Exception)". A menos que você esteja trabalhando com um código que ignore isso ou precise capturar exceções que saem do sistema, é recomendável usar o acima.
Peter Cassetta

@PeterCassetta quando alguém iria querer pegar o sistema saindo de exceções? Parece o fio condutor da pergunta que não queremos capturar isso, mas não entendo o porquê. Por que não geralmente?
Charlie Parker

68

Para capturar todas as exceções possíveis, pegue BaseException. Está no topo da hierarquia de exceção:

Python 3: https://docs.python.org/3.5/library/exceptions.html#exception-hierarchy

Python 2.7: https://docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

Mas, como outras pessoas mencionaram, você normalmente não precisaria disso, apenas para casos específicos.


1
Deseja salvar o progresso de um trabalho de longa duração depois de pressionar Ctrl-C tão incomum?
usar o seguinte

54

Exemplo muito simples, semelhante ao encontrado aqui:

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

Se você estiver tentando capturar TODAS as exceções, coloque todo o seu código na instrução "try:", no lugar de 'print "Executando uma ação que pode gerar uma exceção."'.

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

No exemplo acima, você veria a saída nesta ordem:

1) Realizando uma ação que pode gerar uma exceção.

2) Finalmente, é chamado diretamente após a execução da instrução try, independentemente de uma exceção ser lançada ou não.

3) "Uma exceção foi lançada!" ou "Tudo parece ótimo!" dependendo se uma exceção foi lançada.

Espero que isto ajude!


26

Existem várias maneiras de fazer isso, em particular no Python 3.0 e superior.

Abordagem 1

Essa é uma abordagem simples, mas não recomendada, porque você não saberia exatamente qual linha de código está lançando a exceção:

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

Abordagem 2

Essa abordagem é recomendada porque fornece mais detalhes sobre cada exceção. Inclui:

  • Número da linha do seu código
  • Nome do arquivo
  • O erro real de maneira mais detalhada

A única desvantagem é que o tracback precisa ser importado.

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()

21

Acabei de descobrir esse pequeno truque para testar nomes de exceção no Python 2.7. Às vezes, eu lidei com exceções específicas no código, então eu precisava de um teste para ver se esse nome está dentro de uma lista de exceções manipuladas.

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception

2
try:
    whatever()
except:
    # this will catch any exception or error

Vale ressaltar que isso não é uma codificação Python adequada. Isso também detectará muitos erros que você pode não querer detectar.


basta usar, exceto não armazenar em cache todas as exceções, conforme mencionado em outras respostas. Você precisa usar o BaseException para esse fim, mas como você disse, ninguém deve capturar todas as exceções como essa. Eu acho que é ok para começar, se o objetivo é adicionar mais granular, exceto durante o desenvolvimento, mas eu não acho que vai ser ...
Pyglouthon
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.