ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

J
Jonathan

除了一个简单的 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 子句捕获,但not 通过 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,您希望程序停止,而不是捕获错误并继续运行。但是,如果您想在存在之前进行清理,您可以捕获其中一个/两个。
O
Oren

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

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:
g
gitaarik

要捕获所有可能的异常,请捕获 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 这就是信号处理程序的用途。它是首先引发 KeyboardInterruptSIGINT 的默认信号处理程序。当然,您可以捕获 KeyboardInterrupt,但它只是可能提前终止程序的众多信号之一。这些不会产生任何异常,因此您不妨统一处理它们。
注意:像这样使用 BaseException 很少是你想要的。你真的想捕捉键盘中断和 sys.exit 吗?可能不是!所有用户定义的异常都应继承自 Exception。看看异常类层次结构。 dotnettutorials.net/wp-content/uploads/2020/07/…
E
Erion S

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

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

这可能无法捕获所有异常,因为所有异常的基类都是 BaseException 并且我遇到了不在 Exception 类族中的生产代码。有关这方面的详细信息,请参见 docs.python.org/3/library/…
这不会捕获所有异常。
从技术上讲,它应该捕获所有非系统退出异常。来自@DDay 链接的文档:“异常BaseException:所有内置异常的基类。它并不意味着由用户定义的类直接继承(为此,使用异常)。”除非您正在使用忽略这一点的代码,或者您需要捕获系统退出异常,否则上述内容应该可以使用。
并非所有异常都具有 message 属性。
因为在 Python 3 中 print 是一个函数而不是语句。因此你需要用 () 来调用它。例如打印(e.message)
g
gitaarik

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

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) finally 在执行 try 语句后直接调用,无论是否抛出异常。

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

希望这可以帮助!


我的工作是通过 HPC 管理器运行的。我想捕捉(slurm、qsub、condor)经理何时退出(用我的自定义电子邮件向自己发送电子邮件)。 except: 会发现吗?但它并没有给我e的句柄:(
除了异常,错误:^SyntaxError:无效语法
@Tony 尝试:except Exception as error: - 如果您正在运行 Python3。
g
grepit

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

方法一

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

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

bad_method()

方法二

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

代码的行号

文件名

更详细的实际错误

唯一的缺点是需要导入回溯。

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

我刚刚发现了这个在 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 的新问题——如果之前没有问过的话。加油:)
T
Tamil Selvan

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

Python 3

import traceback

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

这是一个。
Y
Yuval Adam
try:
    whatever()
except:
    # this will catch any exception or error

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


只需使用 except 不要缓存其他答案中提到的所有异常。为此,您必须使用 BaseException ,但正如您所说,没有人应该像这样捕获所有异常。我想如果目标是在开发期间添加更多粒度,那么一开始是可以的,但我认为不会......
H
Hossein Kalbasi

首先,您希望它们破坏您的代码的异常(因为当发生此错误时,您的代码无论如何都不会运行!)以及您希望静默/顺利捕获的异常。尝试区分它们。您可能不想捕获所有异常!

其次,您可以花时间查看流程日志,而不是捕获所有内容。假设您收到了一个不同的/第三方异常,例如来自像 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 异常层次结构 hereExceptionBaseException 之间的区别在于,Exception 不会捕获 SystemExitKeyboardInterruptGeneratorExit