ChatGPT解决这个技术问题 Extra ChatGPT

如何正确忽略异常

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

以下是正确的方法吗?

try:
    shutil.rmtree(path)
except:
    pass
奇怪的是直到现在没人提到它(我在回答中提到过),但是对于这个特定的功能,你可以做 shutil.rmtree(path, ignore_errors=True)。但是,这不适用于大多数功能。
考虑忽略异常时的重要阅读:Why is “except: pass” a bad programming practice?
想象一下在现实生活中这样做。尝试:get_cash('$1000') except: pass # meh,它可能会没事

S
SuperStormer
try:
    doSomething()
except Exception: 
    pass

或者

try:
    doSomething()
except: 
    pass

不同之处在于第二个也将捕获 KeyboardInterruptSystemExit 和类似的东西,它们直接从 BaseException 派生,而不是 Exception

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

尝试语句

例外

但是,捕获每个错误通常是不好的做法 - 请参阅 Why is "except: pass" a bad programming practice?


请注意,StopIteration 和 Warning 也都继承自 Exception。根据您的需要,您可能希望从 StandardError 继承。
这是真的,但如果你不小心,你可能会遇到一些微妙的错误(特别是如果你正在做一些事情而不是传递 StopIteration)。
-1,try: shuti.rmtree(...) except: pass 将粗略地抑制任何错误(即使您拼错 shutil 导致 NameError) - 至少执行 except OSError:
这个答案虽然内容丰富,但缺少一个关键信息——你永远不应该以这种方式捕获异常。相反,您应该始终尝试仅捕获您关心的异常,否则在寻找被通用“例外”隐藏的微不足道的错误时,您将做噩梦。有关更多信息,请参阅 dbr 的答案。 (我知道这不是最初的问题 - 但任何寻找这个的人都会拿走你的片段并按原样使用它)
对于 Python 3.4 之后的版本,应接受 Jabbas 的回答:stackoverflow.com/a/18677839/7162168
w
wim

通常认为最佳做法是只捕获您感兴趣的错误。在 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

shutil.rmtree 不是最好的例子,因为您只需将 ignore_errors=True 用于该功能。
真的很喜欢这个答案,但你没有解释你是如何从 Errno 2errno.ENOENT 的。可能对很多人都有帮助。 ;) 有关详细信息,请参阅 Python Standard Errno System Symbols
J
Jason Baker

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

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

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

如果你的意思是你想对异常采取行动而不阻止异常进入堆栈,那么你需要这样的东西:

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

M
Mr_and_Mrs_D

首先我引用 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

那很好。这样做更好 \n sp=suppress(Exception)\n with sp:\n # your code
c
cbare

为了完整性:

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


R
Russia Must Remove Putin

如何正确忽略异常?

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

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

具体到例子:

代替

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 中工作,请参阅下一节:

蟒蛇 2 和 3:

当你只想做一个 try/except 而不处理异常时,你如何在 Python 中做到这一点?以下是正确的方法吗?尝试:shutil.rmtree(路径)除了:通过

对于 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 库中获取 that 特定的错误号,如果没有,则重新引发:

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 会引发原始异常,这可能是您在这种情况下想要的。写得更简洁,因为我们真的不需要在异常处理中显式地 pass 使用代码:

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

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

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


最后在这种情况下对 else 进行了很好的解释。并且要补充一点,finally始终在任何(或无例外)之后运行。
c
citynorman

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

import fuckit

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

helper()

+1 因为你肯定让我很开心,因为在这个源代码中你可以学到一些非常有用的东西,比如修改实时堆栈
f
faruk13

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

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

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

P
Peter Mortensen

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

m
miksus

好吧,这不是 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 的东西)以不使潜在的异常静音。异常类型、实际异常及其回溯作为(位置)参数传递。您可以使用这些来确定要做什么。

这应该返回 True 以使可能的异常静音。

这应该返回 None (或被认为是 False 的东西)以不使潜在的异常静音。

异常类型、实际异常及其回溯作为(位置)参数传递。您可以使用这些来确定要做什么。

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


优雅但不明显,但实际上很酷
D
Dylan Strudwick

我通常只是这样做:

try:
    doSomething()
except:
    _ = ""

我建议您将 _ = "" 替换为 pass
如果你在代码中使用这个片段,在这个块之前分配了变量 _,如果发生异常,那么在这个块之后,变量的值将会改变。