如何正确忽略异常


776

当您只想执行try-except但不处理异常时,如何在Python中进行呢?

以下是正确的方法吗?

try:
    shutil.rmtree(path)
except:
    pass

10
奇怪的是,到目前为止还没有人提到它(我在回答中做了),但是对于此特定功能,您可以这样做shutil.rmtree(path, ignore_errors=True)。但是,这不适用于大多数功能。
亚伦·霍尔

9
在考虑忽略异常时的重要读物:为什么“ except:pass”是不好的编程习惯?

3
想象一下在现实生活中这样做。试试:get_cash('$ 1000')除外:通过
#meh

Answers:


1039
try:
    doSomething()
except: 
    pass

要么

try:
    doSomething()
except Exception: 
    pass

所不同的是,第一个也将赶上KeyboardInterruptSystemExit和类似的东西,这是直接来源于exceptions.BaseException,没有exceptions.Exception

有关详细信息,请参见文档:


4
请注意,StopIteration和Warning也都继承自Exception。根据您的需求,您可能希望从StandardError继承。
本·布兰克

1
的确如此,但是如果您不小心,可能会遇到一些细微的错误(特别是如果您正在执行其他操作而不是传递StopIteration)。
杰森·贝克

17
-1,try: shuti.rmtree(...) except: pass将粗略地抑制任何错误(即使您拼错了shutil导致NameError),至少也可以这样做except OSError:
dbr 2012年

43
这个答案虽然提供了很多信息,但却缺少了至关重要的信息-您永远不要以这种方式捕获异常。相反,您应该始终尝试仅捕获自己关心的异常,否则,在寻找普通的“ except”所隐藏的琐碎错误时,您将陷入噩梦。有关更多信息,请参见dbr的答案。(我知道这不是最初的问题-但是任何寻找此问题的人都只会拿您的代码片段并按原样使用它)
johndodo

139

通常,仅捕获您感兴趣的错误是最佳实践。在这种情况下,shutil.rmtree可能是OSError

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

如果要静默忽略该错误,则可以执行以下操作:

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

为什么?说您(以某种方式)不小心将整数而不是字符串传递给函数,例如:

shutil.rmtree(2)

它将给出错误“ TypeError:强制转换为Unicode:需要字符串或缓冲区,找到int” -您可能不想忽略它,这可能很难调试。

如果您确实想忽略所有错误,请抓住Exception而不是仅仅except:声明。同样,为什么呢?

不指定异常会捕获所有异常,包括SystemExit例如sys.exit()使用的异常:

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

将此与以下内容进行比较,即可正确退出:

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

如果您想编写更好的行为代码,则OSError异常可以表示各种错误,但是在上面的示例中,我们仅想忽略Errno 2,因此我们可以更加具体:

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.rmtree是不是最好的例子,因为你只需使用ignore_errors=True该功能..
维姆

113

当您只想尝试捕获而不处理异常时,如何在Python中执行呢?

这取决于您所说的“处理”。

如果您打算不采取任何措施就将其捕获,则发布的代码将起作用。

如果您是想对异常采取措施而又不阻止异常上升,那么您需要这样的东西:

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

88

首先,我从这个话题中引述杰克·奥康纳的答案。引用的线程已关闭,所以我在这里写:

“ Python 3.4中引入了一种新的方法:

from contextlib import suppress

with suppress(Exception):
    # your code

这是添加了它的提交:http : //hg.python.org/cpython/rev/406b47c64480

这是作者Raymond Hettinger,讨论了这一点以及其他各种Python热度:https ://youtu.be/OSGv2VnC0go ? t = 43m23s

我对此的补充是Python 2.7等效项:

from contextlib import contextmanager

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

然后像在Python 3.4中一样使用它:

with ignored(Exception):
    # your code

55

为了完整性:

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

还要注意,您可以像这样捕获异常:

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

...并重新引发如下异常:

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

...来自python教程的示例。


43

如何正确忽略异常?

有几种方法可以做到这一点。

但是,示例的选择具有一个不包含一般情况的简单解决方案。

特定于示例:

代替

try:
    shutil.rmtree(path)
except:
    pass

做这个:

shutil.rmtree(path, ignore_errors=True)

这是特定于的论点shutil.rmtree。您可以通过执行以下操作来查看有关此操作的帮助,并且您还将看到它还允许错误处理功能。

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

由于这仅涵盖了示例的狭义情况,因此我将进一步说明如果这些关键字参数不存在,该如何处理。

一般的做法

由于上面仅涵盖了示例的狭义情况,因此我将进一步演示如果这些关键字参数不存在,该如何处理。

Python 3.4的新功能:

您可以导入suppress上下文管理器:

from contextlib import suppress

但只禁止最具体的例外:

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

您将默默地忽略FileNotFoundError

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

文档

与其他任何完全抑制异常的机制一样,此上下文管理器仅应用于涵盖非常具体的错误,在这些错误中,静默地继续执行程序是正确的做法。

请注意,suppress并且FileNotFoundError仅在Python 3中可用。

如果您还希望代码也可以在Python 2中运行,请参阅下一节:

Python 2和3:

当您只想尝试/例外而不处理异常时,如何在Python中进行呢?

以下是正确的方法吗?

try :
    shutil.rmtree ( path )
except :
    pass

对于与Python 2兼容的代码,这pass是不执行操作的正确方法。但是,当你做一个光秃秃的except:,这是一样的做except BaseException:,其中包括GeneratorExitKeyboardInterrupt,和SystemExit,一般来说,你不想要赶上那些东西。

实际上,在命名异常时应尽可能具体。

这是Python(2)异常层次结构的一部分,如您所见,如果您捕获了更多常规异常,则可以隐藏您没有想到的问题:

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

您可能想在这里捕获OSError,也许您不关心的异常是没有目录。

我们可以从库中获取特定的错误号errno,如果没有该错误号,则重新引发:

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 

请注意,不加薪将引发原始异常,在这种情况下,这可能就是您想要的。简明扼要,因为pass在异常处理中我们实际上不需要显式地使用代码:

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

11

当您只想尝试捕获而不处理异常时,如何在Python中执行呢?

这将帮助您打印出异常是什么(例如,在不处理异常的情况下尝试捕获并打印异常。)

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

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

仅供参考,else子句可以在所有异常之后执行,并且仅在try中的代码不会引起异常的情况下才会运行。


1
最后else在这方面做了很好的解释。而且要补充一点,finally它将始终在任何(或无例外)之后运行。
not2qubit

5

我需要忽略多个命令中的错误,fuckit做到了

import fuckit

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

helper()

+1是因为您肯定是我的一天,因为在此源代码中您可以学习一些非常有用的内容,例如修改实时堆栈
WBAR

3

在Python中,我们处理与其他语言相似的异常,但是区别在于语法上有些差异,例如,

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...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.