如何正确忽略异常

How to properly ignore exceptions

提问人:Joan Venge 提问时间:4/9/2009 最后编辑:peterhJoan Venge 更新时间:6/19/2022 访问量:1190301

问:

当你只想做一个try-outside而不处理异常时,你如何在Python中做到这一点?

以下是正确的方法吗?

try:
    shutil.rmtree(path)
except:
    pass
python 异常 try-except

评论

17赞 Russia Must Remove Putin 4/19/2017
奇怪的是,直到现在才有人提到它(我在回答中提到了),但对于这个特定功能,你可以做.但是,这不适用于大多数功能。shutil.rmtree(path, ignore_errors=True)
11赞 poke 9/25/2017
在考虑忽略异常时,重要的阅读内容:为什么“except: pass”是一种糟糕的编程实践?
6赞 Grokodile 9/19/2018
想象一下在现实生活中这样做。try: get_cash('$1000') 除了: pass # meh, it might would be fine
0赞 mathengineer 11/14/2022
对我不起作用:我做了一个生成预期溢出的校验和函数:try:a1[3]=a1[0]+a1[1]+a1[2] 除了:pass 在输出窗口生成错误:d:\jlope\Phyton\Prue\prue12_ftdi:33:RuntimeWarning:ushort_scalars中遇到溢出

答:

1216赞 vartec 4/9/2009 #1
try:
    doSomething()
except Exception: 
    pass

try:
    doSomething()
except: 
    pass

不同的是,第二个也会捕获 ,以及类似的东西,它们直接来自 ,而不是 。KeyboardInterruptSystemExitBaseExceptionException

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

但是,捕获每个错误通常是一种不好的做法 - 请参阅为什么“except: pass”是一种糟糕的编程做法?

评论

5赞 Ben Blank 4/9/2009
请注意,StopIteration 和 Warning 也都继承自 Exception。根据您的需要,您可能希望改为从 StandardError 继承。
1赞 Jason Baker 4/9/2009
这是真的,但如果你不小心,你可能会遇到一些微妙的错误(特别是如果你正在做一些事情而不是传递 StopIteration)。
18赞 dbr 7/23/2012
-1,将粗暴地抑制任何错误(即使您拼写错误导致 ) - 至少这样做try: shuti.rmtree(...) except: passshutilNameErrorexcept OSError:
53赞 johndodo 1/20/2016
这个答案虽然信息丰富,但缺少一个关键信息——你永远不应该以这种方式发现异常。相反,你应该总是尝试只捕捉你关心的异常,否则你会在寻找琐碎的错误时做噩梦,这些错误被你的通用“例外”隐藏起来。有关更多信息,请参阅 dbr 的答案。(我知道这不是最初的问题 - 但任何寻找这个的人都会拿走你的片段并按原样使用它)
0赞 dapc 2/25/2021
对于 Python 3.4 之后的版本,应接受 Jabbas 答案:stackoverflow.com/a/18677839/7162168
118赞 Jason Baker 4/9/2009 #2

当您只想在不处理异常的情况下进行尝试捕获时,如何在 Python 中做到这一点?

这取决于你所说的“处理”是什么意思。

如果您打算在不采取任何行动的情况下捕获它,那么您发布的代码将起作用。

如果你的意思是你想对异常执行操作,而不阻止异常在堆栈中上升,那么你需要这样的东西:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown
164赞 dbr 4/10/2009 #3

通常认为,最佳做法是只捕获您感兴趣的错误。在这种情况下,它可能是:shutil.rmtreeOSError

>>> 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” - 您可能不想忽略它,这可能很难调试。

如果您确实想忽略所有错误,请捕获而不是裸露的语句。再说一遍,为什么?Exceptionexcept:

不指定异常会捕获所有异常,包括异常,例如,使用:SystemExitsys.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

评论

3赞 wim 5/23/2020
shutil.rmtree不是最好的例子,因为你只会用于那个功能。ignore_errors=True
1赞 BUFU 10/28/2020
真的很喜欢这个答案,但你没有解释你是如何从..可能对很多人有帮助。;)有关详细信息,请参阅 Python 标准 Errno 系统符号Errno 2errno.ENOENT
11赞 MrChrisRodriguez 11/20/2009 #4
try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

仅供参考,else 子句可以在所有异常之后运行,并且仅在 try 中的代码不会导致异常时运行。

评论

2赞 not2qubit 10/29/2018
最后,在这种情况下做了一个很好的解释。并且要添加,它将始终在任何(或没有例外)之后运行。elsefinally
60赞 cbare 3/6/2010 #5

为了完整起见:

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

此外,多个异常类型可以作为括号中的元组进行处理:

try:
    i_might_fail()
except (ValueError, TypeError) as ex:
    print('I failed with: ', ex)

...或作为单独的 except 子句:

try:
    i_might_fail()
except ValueError:
    print('handling a ValueError...')
except TypeError:
    print('handling a TypeError...')

...请参阅 Python 教程

5赞 Deepak Kumar 'SORTED' 11/18/2010 #6

在 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...
11赞 Irengbam Tilokchan Singh 10/12/2011 #7

当您只想在不处理异常的情况下进行尝试捕获时, 你如何在 Python 中做到这一点?

这将帮助您打印异常是什么:( 即尝试在不处理异常的情况下捕获并打印异常。

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]
122赞 Jabba 9/8/2013 #8

首先,我引用杰克·奥康纳(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

评论

0赞 Kyoko Sasagava 10/14/2021
那很好。最好是这样做的 \n sp=suppress(Exception)\n with sp:\n # 你的代码
46赞 Russia Must Remove Putin 1/22/2015 #9

如何正确忽略异常?

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

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

具体到示例:

而不是

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

文档中:

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

请注意,仅在 Python 3 中可用。suppressFileNotFoundError

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

Python 2 和 3:

当您只想执行 try/except 而不处理异常时, 你如何在 Python 中做到这一点?

以下是正确的方法吗?

try :
    shutil.rmtree ( path )
except :
    pass

对于 Python 2 兼容代码,是使用无操作语句的正确方法。但是当你做一个裸露的,这与做包括 、 和 一样的事情是一样的,一般来说,你不想抓住这些东西。passexcept:except BaseException:GeneratorExitKeyboardInterruptSystemExit

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

这是 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

你可能想在这里捕获一个 OSErlor,也许你不关心的例外是没有目录。

我们可以从库中获取特定错误号,如果没有该错误号,则重新提出: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 
14赞 citynorman 12/2/2018 #10

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

import fuckit

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

helper()

评论

5赞 WBAR 1/12/2020
+1 因为你肯定让我很开心,因为在这个源代码中,你可以学到一些非常有用的东西,比如修改实时堆栈
-5赞 Dylan Strudwick 1/26/2020 #11

我通常只做:

try:
    doSomething()
except:
    _ = ""

评论

9赞 Legorooj 1/29/2020
我建议你用 ._ = ""pass
0赞 Colin 't Hart 10/23/2020
如果你在代码中使用这个片段,在这个块之前分配了变量,如果发生异常,那么在这个块之后,变量的值将发生变化。_
1赞 miksus 10/28/2021 #12

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

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
    • 这应该返回(或被认为是 False 的东西)以不使潜在的异常静音。None
    • 异常类型、实际异常及其回溯作为(位置)参数传递。您可以使用这些来确定要执行的操作。

最后一点,首选 try-except。如果您需要比平时更多的抽象,这可能很有用。

评论

0赞 krafter 2/21/2022
优雅但不明显,但实际上很酷