如何正确忽略异常

时间:2009-04-08 16:23:01

标签: python exception try-except

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

以下是正确的方法吗?

try:
    shutil.rmtree(path)
except:
    pass

12 个答案:

答案 0 :(得分:929)

try:
  doSomething()
except: 
  pass

try:
  doSomething()
except Exception: 
  pass

不同之处在于,第一个还会捕获KeyboardInterruptSystemExit以及类似的内容,这些内容直接来自exceptions.BaseException,而不是exceptions.Exception
有关详细信息,请参阅文档:

答案 1 :(得分:125)

通常认为只捕捉您感兴趣的错误的最佳做法。对于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,因此我们可能更具体:< / p>

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

您也可以import errno并将if更改为if e.errno == errno.ENOENT:

答案 2 :(得分:109)

  

当你只想尝试catch而不处理异常时,你是如何用Python做的?

这取决于“处理”的含义。

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

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

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

答案 3 :(得分:77)

首先我从this thread引用Jack o'Connor的答案。引用的线程已关闭,所以我写在这里:

“在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

答案 4 :(得分: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"

...来自python tutorial

另请注意,您可以捕获此类异常:

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

答案 5 :(得分:40)

  

如何正确忽略异常?

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

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

特定于示例:

而不是

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

来自docs

  

与完全抑制异常的任何其他机制一样,   此上下文管理器应仅用于涵盖非常具体的错误   已经默默地继续执行程序的地方就是这样   正确的事情。

请注意,suppressFileNotFoundError仅适用于Python 3。

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

Python 2&amp; 3:

  

如果您只是想尝试/除外而不处理异常,   你是如何用Python做的?

     

以下是正确的方法吗?

try :
    shutil.rmtree ( path )
except :
    pass

对于Python 2兼容代码,pass是获得“无操作”语句的正确方法。但是当你做一个except:时,这与except BaseException: GeneratorExitKeyboardInterruptSystemExit的行为相同,一般而言,你不想抓住那些东西。

事实上,您应尽可能详细地命名异常。

这是Python(2)exception hierarchy的一部分,正如您所看到的,如果您捕获更多常规异常,您可以隐藏您不期望的问题:

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 

答案 6 :(得分:12)

  

如果您只想尝试捕获而不处理异常,   你是如何用Python做的?

这将帮助您打印异常的内容:(即尝试catch而不处理异常并打印异常。)

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

答案 7 :(得分:9)

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

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

答案 8 :(得分: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...

答案 9 :(得分:1)

我需要忽略多个命令中的错误,而fuckit可以解决问题

import fuckit

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

helper()

答案 10 :(得分:-1)

只需提升相关的异常,就像这样:

try:
     raise NameError('Joan')
 except NameError:
     print 'An exception just raised again by Joan!'
     raise

就这么简单。 :)

有关详细信息,请阅读以下文档: https://docs.python.org/3.6/tutorial/errors.html

答案 11 :(得分:-5)

我通常只是这样做:

try:
    doSomething()
except:
    _ = ""