Como ignorar corretamente exceções


777

Quando você só quer fazer uma tentativa, exceto sem manipular a exceção, como você faz isso no Python?

O seguinte é o caminho certo para fazer isso?

try:
    shutil.rmtree(path)
except:
    pass

10
Estranho que ninguém tenha mencionado até agora (eu fiz na minha resposta), mas para esta função específica, você pode fazer shutil.rmtree(path, ignore_errors=True). Isso não se aplica à maioria das funções, no entanto.
Aaron Hall

9
Leitura importante ao pensar em ignorar exceções: Por que "exceto: passar" é uma prática ruim de programação?
poke

3
Imagine fazer isso na vida real. tente: get_cash ( '$ 1000'), exceto: pass # meh, ele provavelmente vai ficar bem
Grokodile

Vida real:try: rob() except: run()
PatrickT

Respostas:


1039
try:
    doSomething()
except: 
    pass

ou

try:
    doSomething()
except Exception: 
    pass

A diferença é que o primeiro também vai pegar KeyboardInterrupt, SystemExite coisas assim, que são derivadas diretamente exceptions.BaseException, não exceptions.Exception.

Consulte a documentação para obter detalhes:


4
Observe que StopIteration e Warning também herdam de Exception. Dependendo das suas necessidades, você pode herdar do StandardError.
214 Ben Blank

1
Isso é verdade, mas se você não for cuidadoso, poderá encontrar bugs sutis (especialmente se estiver fazendo algo diferente de transmitir a StopIteration).
Jason Baker

17
-1, try: shuti.rmtree(...) except: passsuprimirá de forma grosseira quaisquer erros (mesmo se você cometer shutilum erro de ortografia resultando em a NameError) - pelo menosexcept OSError:
dbr

44
Embora esta resposta seja informativa, falta uma informação crucial - você nunca deve capturar uma exceção dessa maneira. Em vez disso, você deve sempre tentar capturar apenas as exceções que lhe interessam, caso contrário, você terá pesadelos ao caçar bugs triviais, ocultos por seus "exceto" s genéricos. Veja a resposta do dbr para mais informações. (Eu sei que esta não era a pergunta original - mas qualquer um procurando por isso só vai tomar o seu trecho e usá-lo como é)
johndodo

139

Geralmente, é considerado uma boa prática capturar apenas os erros nos quais você está interessado. No caso shutil.rmtree, provavelmente OSError:

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

Se você deseja ignorar silenciosamente esse erro, faça:

try:
    shutil.rmtree(path)
except OSError:
    pass

Por quê? Digamos que você (de alguma forma) passe acidentalmente a função um número inteiro em vez de uma string, como:

shutil.rmtree(2)

Ele exibirá o erro "TypeError: coagindo para Unicode: precisa de string ou buffer, int encontrado" - você provavelmente não deseja ignorar isso, o que pode ser difícil de depurar.

Se você definitivamente deseja ignorar todos os erros, pegue em Exceptionvez de uma except:declaração simples . Novamente, por que?

Não especificar uma exceção captura todas as exceções, incluindo a SystemExitexceção que, por exemplo, sys.exit()usa:

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

Compare isso com o seguinte, que sai corretamente:

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
shell:~$ 

Se você deseja escrever um código de comportamento cada vez melhor, a OSErrorexceção pode representar vários erros, mas no exemplo acima, queremos apenas ignorar Errno 2, para que possamos ser ainda mais específicos:

import errno

try:
    shutil.rmtree(path)
except OSError as e:
    if e.errno != errno.ENOENT:
        # ignore "No such file or directory", but re-raise other errors
        raise

1
shutil.rmtreenão é o melhor exemplo, porque você usaria apenas ignore_errors=Truepara essa função ..
wim

113

Quando você deseja apenas tentar capturar sem manipular a exceção, como você faz isso no Python?

Depende do que você quer dizer com "manuseio".

Se você deseja capturá-lo sem executar nenhuma ação, o código que você postou funcionará.

Se você quer dizer que deseja executar uma exceção sem interromper a exceção de subir a pilha, então deseja algo como isto:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown

88

Primeiro cito a resposta de Jack o'Connor neste tópico . O thread referenciado foi fechado, então eu escrevo aqui:

"Existe uma nova maneira de fazer isso no Python 3.4:

from contextlib import suppress

with suppress(Exception):
    # your code

Aqui está o commit que o adicionou: http://hg.python.org/cpython/rev/406b47c64480

E aqui está o autor, Raymond Hettinger, falando sobre isso e todos os tipos de gostosuras de Python: https://youtu.be/OSGv2VnC0go?t=43m23s

Minha adição a isso é o equivalente ao Python 2.7:

from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

Então você o usa como no Python 3.4:

with ignored(Exception):
    # your code

55

Para completar:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")

Observe também que você pode capturar a exceção assim:

>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print("Handling run-time error:", err)

... e redigite a exceção assim:

>>> try:
...     raise NameError('HiThere')
... except NameError:
...     print('An exception flew by!')
...     raise

... exemplos do tutorial python .


43

Como ignorar corretamente exceções?

Existem várias maneiras de fazer isso.

No entanto, a escolha do exemplo tem uma solução simples que não cobre o caso geral.

Específico para o exemplo:

Ao invés de

try:
    shutil.rmtree(path)
except:
    pass

Faça isso:

shutil.rmtree(path, ignore_errors=True)

Este é um argumento específico para shutil.rmtree. Você pode ver a ajuda fazendo o seguinte, e também pode permitir a funcionalidade de erros.

>>> import shutil
>>> help(shutil.rmtree)

Como isso cobre apenas o caso restrito do exemplo, demonstrarei mais detalhadamente como lidar com isso se esses argumentos de palavra-chave não existirem.

Abordagem geral

Como o descrito acima cobre apenas o caso restrito do exemplo, demonstrarei mais detalhadamente como lidar com isso se esses argumentos de palavra-chave não existirem.

Novo no Python 3.4:

Você pode importar o suppressgerenciador de contexto:

from contextlib import suppress

Mas suprima apenas a exceção mais específica:

with suppress(FileNotFoundError):
    shutil.rmtree(path)

Você ignorará silenciosamente um FileNotFoundError:

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

Dos documentos :

Como com qualquer outro mecanismo que suprime completamente as exceções, esse gerenciador de contexto deve ser usado apenas para cobrir erros muito específicos, onde a continuação silenciosa da execução do programa é conhecida como a coisa certa a se fazer.

Observe que suppresse FileNotFoundErrorsó estão disponíveis no Python 3.

Se você deseja que seu código funcione também no Python 2, consulte a próxima seção:

Python 2 e 3:

Quando você só quer fazer uma tentativa / exceto sem manipular a exceção, como você faz isso no Python?

O seguinte é o caminho certo para fazer isso?

try :
    shutil.rmtree ( path )
except :
    pass

Para código compatível com Python 2, passé a maneira correta de ter uma declaração que não é operacional. Mas quando você faz um nu except:, isso é o mesmo que fazer except BaseException:o que inclui GeneratorExit, KeyboardInterrupte SystemExit, e, em geral, você não quer pegar essas coisas.

De fato, você deve ser o mais específico possível em nomear a exceção.

Aqui está parte da hierarquia de exceções do Python (2) e, como você pode ver, se você capturar exceções mais gerais, poderá ocultar problemas que não esperava:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

Você provavelmente deseja capturar um OSError aqui, e talvez a exceção com a qual você não se importa seja se não houver diretório.

Podemos obter esse número de erro específico da errnobiblioteca e re-aumentar se não tivermos isso:

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

Observe que um aumento simples gera a exceção original, que provavelmente é o que você deseja neste caso. Escrito de forma mais concisa, pois não precisamos explicitamente passcom código no tratamento de exceções:

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 

11

Quando você deseja apenas tentar capturar sem manipular a exceção, como você faz isso no Python?

Isso ajudará você a imprimir qual é a exceção :( ou seja, tente capturar sem manipular a exceção e imprima a exceção.)

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]

10
try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

Para sua informação, a cláusula else pode ser executada após todas as exceções e só será executada se o código na tentativa não causar uma exceção.


1
Finalmente, uma boa explicação elsepara esse contexto. E para adicionar isso finally, sempre será executado após qualquer (ou nenhuma exceção).
Not2qubit # 29/18

5

Eu precisava ignorar erros em vários comandos e fuckit fez o truque

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()

+1 porque você definitivamente fez o meu dia porque, dentro deste código-fonte, você pode aprender algumas coisas extremamente úteis, como modificar a pilha
ativa

3

No Python, lidamos com exceções semelhantes a outra linguagem, mas a diferença é alguma diferença de sintaxe, por exemplo,

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...

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.