【问题标题】:How can I write a `try`/`except` block that catches all exceptions?如何编写一个捕获所有异常的 `try`/`except` 块?
【发布时间】:2011-06-26 19:37:50
【问题描述】:

如何编写一个try/except 块来捕获所有异常?

【问题讨论】:

  • 在大多数情况下,如果您试图捕获任何异常,您可能会做错事。我的意思是你可以简单地在你的代码中拼错一些东西,你甚至不知道它。捕获特定异常是一种很好的做法。
  • 更准确地说,捕获所有可能的异常只有在它们被静默捕获时才是一个问题。除了将捕获的错误消息打印到sys.stderr 并可能记录下来之外,很难想到这种方法还有什么合适的地方。这是一个完全有效且常见的例外。
  • 你试过了吗:try: whatever() except Exception as e: exp_capture()

标签: python exception


【解决方案1】:

我正在添加可以捕获具有完整回溯的异常的奖励方法,这可以帮助您更多地了解错误。

Python 3

import traceback

try:
    # your code goes here
except Exception as e:
    print(e)
    traceback.print_exc()

【讨论】:

  • 就是这个。
【解决方案2】:

你可以,但你可能不应该:

try:
    do_something()
except:
    print("Caught it!")

但是,这也会捕获像 KeyboardInterrupt 这样的异常,而您通常不希望这样,对吗?除非您立即重新引发异常 - 请参阅以下示例 from the docs

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print("I/O error({0}): {1}".format(errno, strerror))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise

【讨论】:

  • 你真的应该打印到标准错误。
  • 我非常非常非常不同意“不应该”的说法。你应该谨慎行事。有时您处理的第三方库(有时是动态加载的!!)由于异常而变得非常疯狂,并且将它们全部跟踪下来可能是一项非常痛苦的任务,如果您错过了一个,您将有一个非常非常系统中巨大的痛苦错误。话虽如此,最好尽可能多地追踪并妥善处理它们,然后为你错过的人准备一个备份。
  • 我也觉得奇怪的是,在你不声明实例变量的鸭式打字语言中,它突然非常担心不输入所有异常。嗯!
  • 仍然缺少except Exception:
【解决方案3】:

要捕获所有可能的异常,请捕获BaseException。它位于异常层次结构的顶部:

Python 3: https://docs.python.org/3.9/library/exceptions.html#exception-hierarchy

Python 2.7: https://docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

但正如其他人提到的,您通常不需要这个,仅用于特定情况。

【讨论】:

  • 是否希望在按 Ctrl-C 后保存长时间运行的作业的进度这样不寻常?
  • 我的工作是通过 HPC 管理器运行的。我想捕捉(slurm、qsub、condor)经理何时退出(用我的自定义电子邮件向自己发送电子邮件)。 except: 会明白吗?但它并没有给我e 的句柄:(
  • In Python, all exceptions must be instances of a class that derives from BaseException,但是如果您可以在一般情况下省略它 - 省略它,问题是,关于它的葡萄酒。
  • @BallpointBen 这就是信号处理程序的用途。这是SIGINT 的默认信号处理程序,它首先引发KeyboardInterrupt。当然,您可以捕捉到KeyboardInterrupt,但这只是可能提前终止您的程序的众多信号之一。这些不会产生任何异常,因此您不妨统一处理它们。
【解决方案4】:

有多种方法可以做到这一点,特别是对于 Python 3.0 及更高版本

方法一

这是一种简单的方法,但不推荐使用,因为您无法确切知道哪一行代码实际引发了异常:

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

方法 2

建议使用此方法,因为它提供了有关每个异常的更多详细信息。它包括:

  • 代码的行号
  • 文件名
  • 更详细的实际错误

唯一的缺点是需要导入tracback。

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()

【讨论】:

  • 我的工作是通过 HPC 管理器运行的。我想捕捉(slurm、qsub、condor)经理何时退出(用我的自定义电子邮件向自己发送电子邮件)。 except: 会明白吗?但是它并没有给我e的句柄:(
  • 是否可以连接到traceback.print_exc()
【解决方案5】:

非常简单的示例,类似于此处找到的示例:

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

如果您尝试捕获所有异常,请将所有代码放在“try:”语句中,而不是“print“执行可能引发异常的操作。”。

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

在上面的示例中,您会按以下顺序看到输出:

1) 执行可能引发异常的操作。

2)无论是否抛出异常,在执行try语句后直接调用finally。

3) “抛出异常!”或“一切看起来都很棒!”取决于是否抛出异常。

希望这会有所帮助!

【讨论】:

  • 我的工作是通过 HPC 管理器运行的。我想捕捉(slurm、qsub、condor)经理何时退出(用我的自定义电子邮件向自己发送电子邮件)。 except: 会明白吗?但是它并没有给我e的句柄:(
  • 例外异常,错误:^SyntaxError: invalid syntax
  • @Tony try: except Exception as error: -- 如果你正在运行 Python3。
【解决方案6】:

我刚刚发现了这个在 Python 2.7 中测试异常名称的小技巧。有时我在代码中处理了特定的异常,所以我需要测试一下该名称是否在处理的异常列表中。

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception

【讨论】:

  • 我的工作是通过 HPC 管理器运行的。我想捕捉(slurm、qsub、condor)经理何时退出(用我的自定义电子邮件向自己发送电子邮件)。 except: 会明白吗?但它并没有给我e 的句柄:(
  • 老实说,我对HPC并不熟悉...如果它与python集成/用于python它应该实现相应的异常。如果不是,您可以尝试拥有它的第 3 部分库(不知道是哪个),或者制作一个任务侦听器来搜索 HPC 设置的标志。如果一切都失败了,您可以尝试自己编写一些代码,“异常”类是可继承的并深入到进程/驱动程序中。除此之外,由于缺乏更多信息和 SO 的无意见政策,我建议在标题和标签中询问 HPC 的新问题——如果之前没有问过的话。欢呼:)
【解决方案7】:

您可以这样做来处理一般异常

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message

【讨论】:

  • 这可能无法捕获所有异常,因为所有异常的基类都是 BaseException 并且我遇到了不在 Exception 类家族中的生产代码。有关详细信息,请参阅docs.python.org/3/library/…
  • 这不会捕获所有异常。
  • 从技术上讲,它应该捕获所有非系统退出异常。来自@DDay 链接的文档:“exception BaseException:所有内置异常的基类。它并不意味着由用户定义的类直接继承(为此,请使用 Exception)。”除非您正在使用忽略这一点的代码,或者您需要捕获系统退出异常,否则上述内容应该可以使用。
  • @PeterCassetta 什么时候想要捕获系统退出异常?似乎我们不想抓住这些问题的共同点,但我不明白为什么。为什么不经常?
  • 并非所有异常都具有message 属性。
【解决方案8】:

除了一个简单的except: 子句(正如其他人所说你不应该使用它),你可以简单地捕捉Exception

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

您通常只会考虑在代码的最外层执行此操作,例如,如果您想在终止之前处理任何其他未捕获的异常。

except Exception 相对于 except 的优势在于它不会捕获一些异常,最明显的是 KeyboardInterruptSystemExit:如果你捕获并吞下了它们,那么你可能会很难任何人都可以退出您的脚本。

【讨论】:

  • 我也有同样的想法,但它们是一个缺点,假设它们在一次被捕获时有两个错误,并且除了你只是在打印之外,你将退出 try 块并且你永远不会知道第二个错误...
  • 对于任何想知道的人来说,完全出乎我的意料,至少在 python 2.x 中,这仍然会捕获非异常子类化的东西,例如 int。
  • @JosephGarvin,这是不正确的,即这不会捕获不属于 Exception 的“非异常”。请注意,不可能将int 引发为异常,并且尝试这样做会引发TypeError 异常,在这种情况下,封闭的except Exception 子句将捕获该异常。另一方面,可以提出旧式类并将其限定为不子类 Exception 的“非异常” - 这 被一个裸露的 except 子句捕获,但是不是 except Exception 子句。
  • @JosephGarvin 检查这个博客条目:chris-lamb.co.uk/posts/no-one-expects-string-literal-exception 我和@Yoel 一起做这个,你的测试只是掩盖了TypeError
  • @CharlieParker 如果这是您想要的,但大多数情况下您不想要,抓住它们并没有错。调用sys.exit() 通常意味着您希望应用程序终止,但如果您捕获 SystemExit 它不会。同样,如果您在正在运行的脚本(Windows 上的 Ctrl-break)上按下 control-C,您希望程序停止,而不是捕获错误并继续运行。但是,如果您想在存在之前进行清理,则可以捕获其中一个/两个。
【解决方案9】:
try:
    whatever()
except:
    # this will catch any exception or error

值得一提的是,这不是正确的 Python 编码。这也将捕获许多您可能不想捕获的错误。

【讨论】:

  • 只使用除了不缓存其他答案中提到的所有异常。为此,您必须使用 BaseException ,但正如您所说,没有人应该像这样捕获所有异常。我想如果目标是在开发期间添加更精细的内容,那么一开始是可以的,但我认为不会......
猜你喜欢
  • 1970-01-01
  • 2022-11-29
  • 2015-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-09
相关资源
最近更新 更多