当你只想做一个try-except而不处理异常时,你在Python中如何做呢?

下面的方法是正确的吗?

try:
    shutil.rmtree(path)
except:
    pass

当前回答

通常认为最佳实践是只捕获您感兴趣的错误。在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: coercing to Unicode: need string or buffer, int found”——你可能不想忽略它,这可能很难调试。

如果你确实想忽略所有错误,捕获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

其他回答

好吧,这不是一个try-except,但仍然是另一种处理异常的方法,如果你是面向对象编程:

class MyExceptionHandler:

    def __enter__(self):
        ... # Do whatever when "with" block is started
        return self

    def __exit__(self, exc_type, exc_value, tb):
        return True

然后是实际的代码:

with MyExceptionHandler():
     ... # Code that may or may not raise an exception
     shutil.rmtree(path)

这是怎么回事?

__enter__在进入with块时运行。 __exit__在退出with块时运行 这应该返回True以关闭可能的异常。 这应该返回None(或被认为是False的东西),以避免关闭潜在的异常。 异常类型、实际异常及其回溯作为(位置)参数传递。你可以用这些来决定要做什么。

最后要注意的是,更喜欢try-except。如果您需要比平时更多的抽象,这可能会很有用。

如何正确地忽略异常?

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

然而,例子的选择有一个简单的解决方案,不包括一般情况。

具体到示例:

而不是

try:
    shutil.rmtree(path)
except:
    pass

这样做:

shutil.rmtree(path, ignore_errors=True)

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

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

由于这只涵盖了示例的狭窄情况,因此我将进一步演示在这些关键字参数不存在的情况下如何处理它。

一般方法

由于以上内容只涵盖了本例的狭窄情况,因此我将进一步演示在这些关键字参数不存在的情况下如何处理这个问题。

Python 3.4新增功能:

你可以导入抑制上下文管理器:

from contextlib import suppress

但只抑制最具体的例外:

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

你会默默地忽略FileNotFoundError:

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

从文档中可以看出:

与其他完全抑制异常的机制一样, 这个上下文管理器应该只用于覆盖非常特定的错误 静默地继续执行程序是已知的 这是正确的做法。

注意,suppress和FileNotFoundError仅在Python 3中可用。

如果你想让你的代码也能在python2中工作,请参阅下一节:

Python 2和3:

当你只想执行try/except而不处理异常时, 用Python怎么做? 下面的方法是正确的吗? 试一试: shutil。Rmtree(路径) 除了: 通过

对于兼容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

您可能想在这里捕获一个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 

注意,纯raise会引发原始异常,这可能就是您在本例中想要的结果。写得更简洁,因为我们真的不需要在异常处理中显式地传递代码:

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

通常认为最佳实践是只捕获您感兴趣的错误。在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: coercing to Unicode: need string or buffer, int found”——你可能不想忽略它,这可能很难调试。

如果你确实想忽略所有错误,捕获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
try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

供您参考,else子句可以放在所有异常之后,只有在try中的代码没有导致异常时才会运行。

我通常会这样做:

try:
    doSomething()
except:
    _ = ""