如何正确忽略异常

Joa*_*nge 734 python exception try-except

如果您只是想尝试 - 除非不处理异常,您如何在Python中执行此操作?

以下是正确的方法吗?

try:
    shutil.rmtree(path)
except:
    pass
Run Code Online (Sandbox Code Playgroud)

var*_*tec 991

try:
  doSomething()
except: 
  pass
Run Code Online (Sandbox Code Playgroud)

要么

try:
  doSomething()
except Exception: 
  pass
Run Code Online (Sandbox Code Playgroud)

不同的是,第一个也将捕获KeyboardInterrupt,SystemExit而这样的东西,直接来自exceptions.BaseException,而不是exceptions.Exception.
有关详情,请参阅文档

  • 这个答案虽然提供了丰富的信息,却缺少一个至关重要的信息 - 你不应该以这种方式捕获异常.相反,你应该总是试着抓住你关心的例外情况,否则你在追捕琐碎的错误时会做噩梦,被你的通用"除外"所隐藏.有关详细信息,请参阅dbr的答案.(我知道这不是原来的问题 - 但任何寻找此问题的人都会把你的代码片段按原样使用) (35认同)
  • -1,`try:shuti.rmtree(...)除了:pass`将粗略地抑制任何错误(即使你拼错了`shutil`导致`NameError`) - 至少做``除了OSError:` (15认同)
  • 请注意,StopIteration和Warning也都从Exception继承.根据您的需要,您可能希望继承StandardError. (4认同)

dbr*_*dbr 129

通常认为最好的方法是只捕获您感兴趣的错误.在shutil.rmtree可能的情况下OSError:

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

如果您想静默忽略该错误,您可以:

try:
    shutil.rmtree(path)
except OSError:
    pass
Run Code Online (Sandbox Code Playgroud)

为什么?假设你(不知何故)意外地将函数传递给整数而不是字符串,例如:

shutil.rmtree(2)
Run Code Online (Sandbox Code Playgroud)

它会给错误"类型错误:强迫为Unicode:需要字符串或缓冲区,诠释发现" -你可能不想忽略,这可能是难以调试.

如果你肯定想要忽略所有错误,请抓住Exception而不是简单的except:陈述.再次,为什么?

未指定异常会捕获每个异常,包括SystemExit例如sys.exit()使用的异常:

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>
Run Code Online (Sandbox Code Playgroud)

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

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
shell:~$ 
Run Code Online (Sandbox Code Playgroud)

如果你想编写更好的行为代码,OSError异常可以表示各种错误,但在上面的例子中我们只想忽略Errno 2,所以我们可以更具体:

try:
    shutil.rmtree(path)
except OSError, e:
    if e.errno == 2:
        # suppress "No such file or directory" error
        pass
    else:
        # reraise the exception, as it's an unexpected error
        raise
Run Code Online (Sandbox Code Playgroud)

您也可以import errno更改ifif e.errno == errno.ENOENT:

  • `shutil.rmtree` 不是最好的例子,因为你只需使用 `ignore_errors=True` 来实现该函数。 (3认同)

Jas*_*ker 110

当你只想尝试catch而不处理异常时,你如何在Python中做到这一点?

这取决于"处理"的含义.

如果您想在不采取任何措施的情况下捕获它,您发布的代码将起作用.

如果你的意思是你想对异常采取行动而不停止异常上升,那么你想要这样的东西:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown
Run Code Online (Sandbox Code Playgroud)


Jab*_*bba 84

首先,我从这个帖子中引用Jack o'Connor的答案.引用的线程已关闭,所以我写在这里:

"在Python 3.4中有一种新方法可以做到这一点:

from contextlib import suppress

with suppress(Exception):
    # your code
Run Code Online (Sandbox Code Playgroud)

这是添加它的提交: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
Run Code Online (Sandbox Code Playgroud)

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

with ignored(Exception):
    # your code
Run Code Online (Sandbox Code Playgroud)


cba*_*are 54

为了完整性:

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

...来自python教程.

另请注意,您可以像这样捕获异常:

>>> try:
...     this_fails()
... except ZeroDivisionError as detail:
...     print 'Handling run-time error:', detail
Run Code Online (Sandbox Code Playgroud)


Aar*_*all 42

如何正确忽略异常?

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

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

具体到示例:

代替

try:
    shutil.rmtree(path)
except:
    pass
Run Code Online (Sandbox Code Playgroud)

做这个:

shutil.rmtree(path, ignore_errors=True)
Run Code Online (Sandbox Code Playgroud)

这是一个特定的参数shutil.rmtree.您可以通过执行以下操作来查看有关它的帮助,您将看到它也可以允许错误功能.

>>> import shutil
>>> help(shutil.rmtree)
Run Code Online (Sandbox Code Playgroud)

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

一般的做法

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

Python 3.4中的新功能:

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

from contextlib import suppress
Run Code Online (Sandbox Code Playgroud)

但只能压制最具体的异常:

with suppress(FileNotFoundError):
    shutil.rmtree(path)
Run Code Online (Sandbox Code Playgroud)

你会默默地忽略一个FileNotFoundError:

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 
Run Code Online (Sandbox Code Playgroud)

来自文档:

与完全抑制异常的任何其他机制一样,此上下文管理器应该仅用于覆盖非常具体的错误,其中已知正确地继续执行程序是正确的.

请注意,suppressFileNotFoundError仅可在Python 3.

如果您希望代码也在Python 2中工作,请参阅下一节:

Python 2&3:

如果你只是想尝试/除了没有处理异常,你如何在Python中做到这一点?

以下是正确的方法吗?

try :
    shutil.rmtree ( path )
except :
    pass
Run Code Online (Sandbox Code Playgroud)

对于Python 2兼容代码,pass是使用无操作语句的正确方法.但是,当你做一个光秃秃的except:,这是一样做的except BaseException:,其中包括GeneratorExit,KeyboardInterrupt,和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
Run Code Online (Sandbox Code Playgroud)

你可能想在这里捕获一个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 
Run Code Online (Sandbox Code Playgroud)

请注意,裸引发会引发原始异常,这可能是您在这种情况下所需要的.写得更简洁,因为我们不需要pass在异常处理中明确地使用代码:

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


小智 12

当你只想尝试catch而不处理异常时,你如何在Python中做到这一点?

这将帮助您打印异常是什么:(即尝试catch而不处理异常并打印异常.)

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]
Run Code Online (Sandbox Code Playgroud)


小智 10

try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()
Run Code Online (Sandbox Code Playgroud)

FYI else子句可以在所有异常之后执行,并且只有在try中的代码不会导致异常时才会运行.

  • 最后在这种情况下对“else”进行了很好的解释。并补充说 `finally` 将 **always** 在任何(或没有例外)之后运行。 (2认同)

cit*_*man 9

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

import fuckit

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

helper()
Run Code Online (Sandbox Code Playgroud)

  • +1,因为你绝对让我很开心,因为在这个源代码中你可以学到一些非常有用的东西,比如修改实时堆栈 (5认同)

小智 5

在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...
Run Code Online (Sandbox Code Playgroud)