如何编写捕获所有异常的“try”/“except”块?

How can I write a `try`/`except` block that catches all exceptions?

提问人:user469652 提问时间:2/14/2011 最后编辑:Charlie Parkeruser469652 更新时间:5/29/2023 访问量:1137899

问:

如何编写捕获所有异常的 / 块?tryexcept

Python 异常

评论

6赞 vwvolodya 9/4/2014
在大多数情况下,如果你试图抓住任何异常,你可能做错了。我的意思是,你可以简单地在代码中拼错一些东西,你甚至不会知道它。捕获特定异常是一种很好的做法。
36赞 Evgeni Sergeev 5/7/2016
更准确地说,只有当它们被静默捕获时,捕获所有可能的异常才是一个问题。除了将捕获的错误消息打印到并可能记录的位置之外,很难想出这种方法还适合其他位置。这是一个完全有效和常见的例外。sys.stderr
1赞 Charlie Parker 5/3/2020
你试过吗: ?try: whatever() except Exception as e: exp_capture()
0赞 tripleee 7/25/2020
相关新闻: 为什么 except: pass 是一种糟糕的编程实践?
0赞 tripleee 7/4/2021
参见 在 Python 中捕获所有异常的坏主意

答:

10赞 Yuval Adam 2/14/2011 #1
try:
    whatever()
except:
    # this will catch any exception or error

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

评论

0赞 Pyglouthon 10/31/2019
只需使用 except don't cach 所有其他答案中提到的所有异常。为此,您必须使用 BaseException,但正如您所说,没有人应该像这样捕获所有异常。我想如果目标是添加更细粒度,除了在开发过程中之外,这是可以的,但我认为它不会......
752赞 Tim Pietzcker 2/14/2011 #2

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

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

但是,这也将捕获异常,例如您通常不希望那样,是吗?除非您立即重新引发异常 - 请参阅文档中的以下示例:KeyboardInterrupt

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

评论

34赞 Mikel 2/14/2011
可能的解决方法:effbot.org/zone/stupid-exceptions-keyboardinterrupt.htm
9赞 alexia 1/15/2015
你真的应该打印到 stderr。
80赞 Blaze 10/19/2015
我非常非常不同意“不应该”的说法。你应该谨慎地做。有时,您正在处理第三方库(有时是动态加载的!!)时,这些库因异常而变得完全疯狂,并且跟踪它们可能是一项非常痛苦的任务,如果您只错过了一个,那么您的系统中就会有一个非常非常巨大的痛苦错误。话虽如此,最好尽可能多地追踪并适当地处理它们,然后为您错过的那些进行备份。
56赞 Blaze 10/19/2015
我发现同样奇怪的是,在不声明实例变量的鸭子类型语言中,它突然非常关注不键入所有异常。嗯!
9赞 Pedro Gordo 2/7/2019
仍然缺少 .except Exception:
1309赞 Duncan 2/14/2011 #3

除了一个裸露的子句(正如其他人所说,你不应该使用它),你可以简单地抓住 Exceptionexcept:

import traceback
import logging

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

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

与裸露相比,它的优势在于它有一些例外情况是它不会捕获的,最明显的是:如果你捕获并吞下了这些异常,那么你可能会让任何人都很难退出你的脚本。except ExceptionexceptKeyboardInterruptSystemExit

评论

8赞 Joseph Garvin 10/2/2014
对于任何想知道的人,这与我的预期完全相反,这仍然会捕获非异常子类化的东西,例如 ints,至少在 python 2.x 中是这样。
11赞 Yoel 11/14/2016
@JosephGarvin,这是不正确的,即这不会捕获不子类的“非异常”。请注意,不可能将 an 作为例外提出,并且尝试这样做会引发异常,在这种情况下,这就是封闭子句会捕获的内容。另一方面,一个旧式的类可以被提出,并有资格作为一个不子类的“非例外”——这将被一个裸子句捕获,而不是被一个子句捕获。ExceptionintTypeErrorexcept ExceptionExceptionexceptexcept Exception
4赞 Duncan 11/14/2016
@JosephGarvin查看此博客文章: chris-lamb.co.uk/posts/no-one-expects-string-literal-exception 我和@Yoel一起讨论这个问题,您的测试只是掩盖了TypeError
2赞 Duncan 5/4/2020
如果这是你想要的,抓住它们@CharlieParker没有错,但你大多没有。调用通常意味着你希望应用程序终止,但如果你捕获 SystemExit,它不会。同样,如果你在正在运行的脚本上按 control-C(在 Windows 上按 Ctrl-break),你希望程序停止,而不是捕获错误并继续。但是,如果您想在存在之前进行清理,则可以捕获其中之一/两者。sys.exit()
3赞 Duncan 9/30/2020
@CharlieParker你可以尝试捕获所有异常并执行您需要的任何通知,但我不知道 HPC,所以你可能想作为一个新的 SO 问题提出。except BaseException as e: notify_user(e); raise
64赞 Joshua Burns 2/15/2011 #4

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

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语句后直接调用。

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

希望这有帮助!

评论

0赞 Charlie Parker 9/29/2020
我的工作由 HPC 管理器运行。我想捕获(slurm、qsub、condor)管理器何时退出(用我的自定义电子邮件通过电子邮件发送自己)。会抓住吗?但它并没有给我一个把柄,尽管:(except:e
2赞 Tony 3/12/2021
除了异常,错误:^SyntaxError:语法无效
2赞 Joshua Burns 8/4/2021
@Tony尝试: -- 如果您运行的是 Python3。except Exception as error:
119赞 vwvolodya 7/15/2013 #5

您可以这样做来处理常规异常

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

评论

12赞 DDay 6/3/2016
这可能无法捕获所有异常,因为所有异常的基类都是 BaseException,并且我遇到了不在 Exception 类系列中的生产代码。有关详细信息,请参见 docs.python.org/3/library/...
5赞 Andy_A̷n̷d̷y̷ 9/20/2017
这并不能捕获所有异常。
13赞 Peter Cassetta 2/13/2018
从技术上讲,它应该捕获所有非系统退出异常。从文档@DDay链接:“exception BaseException:所有内置异常的基类。它并不意味着由用户定义的类直接继承(为此,请使用 Exception)。除非您正在使用忽略此问题的代码,或者您需要捕获系统退出异常,否则可以使用上述内容。
3赞 nullable 10/20/2020
并非所有异常都具有属性。message
2赞 vwvolodya 12/24/2020
因为在 Python 3 中,print 是一个函数而不是语句。因此,您需要用 () 调用它。例如:print(e.message)
178赞 gitaarik 7/24/2015 #6

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

Python 3:https://docs.python.org/3.11/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))

但正如其他人所提到的,您通常不需要这个,只有在非常特殊的情况下才需要它。

评论

7赞 BallpointBen 8/28/2018
希望在按 Ctrl-C 后保存长时间运行的作业的进度是否不寻常?
0赞 Charlie Parker 9/29/2020
我的工作由 HPC 管理器运行。我想捕获(slurm、qsub、condor)管理器何时退出(用我的自定义电子邮件通过电子邮件发送自己)。会抓住吗?但它并没有给我一个把柄,尽管:(except:e
1赞 jave.web 11/4/2020
In Python, all exceptions must be instances of a class that derives from BaseException,但如果你可以在一般情况下省略它 - 省略它,问题是,关于它的酒。
0赞 chepner 7/24/2021
@BallpointBen 这就是信号处理程序的用途。首先,它是引发的默认信号处理程序。当然,您可以捕获,但这只是可能过早终止程序的众多信号之一。这些不会产生任何异常,因此您不妨统一处理它们。SIGINTKeyboardInterruptKeyboardInterrupt
2赞 John Henckel 2/28/2022
注意:像这样使用很少是你想要的。你真的想抓住键盘中断和 sys.exit 吗?可能不是!所有用户定义的异常都应继承自 。看一下 Exception 类层次结构。dotnettutorials.net/wp-content/uploads/2020/07/......BaseExceptionException
25赞 Danilo 11/28/2016 #7

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

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

评论

0赞 Charlie Parker 9/29/2020
我的工作由 HPC 管理器运行。我想捕获(slurm、qsub、condor)管理器何时退出(用我的自定义电子邮件通过电子邮件发送自己)。会抓住吗?但它并没有给我一个把柄,尽管:(except:e
0赞 Danilo 9/30/2020
老实说,我对 HPC 并不熟悉......如果它与 python 集成/用于 python,它应该实现相应的异常。如果没有,您可以尝试具有它的第 3 部分库(不知道哪个)或制作一个任务侦听器来搜索 HPC 设置的标志。如果所有这些都失败了,您可以尝试自己编写一些代码,“exception”类是可继承的,并深入研究进程/驱动程序。除此之外,由于缺乏更多信息和 SO 的无意见政策,我建议在标题和标签中提出一个新问题 witch HPC - 如果以前没有问过的话。欢呼:)
41赞 grepit 1/28/2019 #8

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

方法 1

这是一种简单的方法,但不建议这样做,因为您不知道到底是哪一行代码实际上引发了异常:

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

评论

0赞 Charlie Parker 9/29/2020
我的工作由 HPC 管理器运行。我想捕获(slurm、qsub、condor)管理器何时退出(用我的自定义电子邮件通过电子邮件发送自己)。会抓住吗?但它并没有给我一个把柄,尽管:(except:e
0赞 Unknow0059 11/7/2020
是否可以连接到?traceback.print_exc()
22赞 Tamil Selvan 12/9/2021 #9

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

Python 3

import traceback

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

评论

1赞 Joshua Pinter 12/25/2021
就是这个。
7赞 Hossein Kalbasi 2/8/2022 #10

首先,有些异常是你希望它们破坏你的代码的(因为当这个错误发生时,你的代码无论如何都不会起作用!),还有一些异常是你想静默/平滑地捕获的。尝试区分它们。您可能不想捕获所有异常!

其次,您可以花时间浏览流程日志,而不是捕获所有内容。假设您收到其他/第三方异常,例如来自 GCP 等云服务提供商的异常。在日志中,您可以找到您得到的异常。然后,你可以做这样的事情:

from google.api_core.exceptions import ServiceUnavailable, RetryError

for i in range(10):
   try:
      print("do something")

   except ValueError:
      print("I know this might happen for now at times! skipping this and continuing with my loop"

   except ServiceUnavailable:
      print("our connection to a service (e.g. logging) of gcp has failed")
      print("initializing the cloud logger again and try continuing ...") 

   except RetryError:
      print("gcp connection retry failed. breaking the loop. try again later!)
      break

对于其余的(可能发生或可能不会发生的错误),如果我遇到意外异常,我会为我的代码崩溃留出空间!这样,我就可以了解正在发生的事情,并通过捕获边缘情况来改进我的代码。

如果您希望它永远不会因为某种原因而崩溃,例如,如果它是嵌入在远程硬件中的代码,您不容易访问,您可以在末尾添加一个通用的异常捕获器:

except Exception as e:
   print(f"something went wrong! - {e}")

您还可以在此处查看 Python 3 异常层次结构。和 的区别在于,不会抓住 、 或ExceptionBaseExceptionExceptionSystemExitKeyboardInterruptGeneratorExit