【问题标题】:How do I have a python function return an exception traceback, or the result?如何让 python 函数返回异常回溯或结果?
【发布时间】:2016-03-12 03:08:15
【问题描述】:

假设我有一个函数:

def ReadFile():
    with open("/etc/passwd") as file:
        data = file.read()

这个函数可能会成功,在这种情况下它需要返回一个结果,或者它可能会失败,在这种情况下我想返回异常的回溯,它将通过电子邮件发送给我,所以我知道我的程序中发生了一些错误,以及究竟是什么失败了。

为此,我可以这样做:

import traceback

def ReadFile():
    try:
        with open("/etc/passwd") as file:
            data = file.read()
    except IOError:
        return traceback.format_exc()
    return data

如果能够成功读取文件,则返回文件内容。否则返回异常的回溯。

traceback.format_exc() 返回一个字符串。如果 ReadFile() 应该返回一个列表,或者如果成功则返回一个元组或整数,那么事情就很简单了——当你调用 ReadFile() 时,如果返回的结果是一个字符串,你就知道它失败了,你可以运行通过电子邮件发送的代码你知道错误,如果结果是你期望的类型(int、tuple、list 或 w/e),那么你知道它是有效的。

如果 ReadFile() 应该返回一个字符串,就像在我的示例中那样,那么确定 ReadFile() 是成功还是失败变得更加困难,因为您需要解析字符串以确定它是否看起来像回溯或您预期的结果。

有没有更好的方法来做到这一点?也许某种方式可以让 traceback 返回某种与 traceback.format_exc() 包含的信息相同的对象,以便更容易确定 ReadFile() 是成功还是失败?

【问题讨论】:

  • 更好的方法是让它在调用点抛出并捕获异常。这就是例外。

标签: python python-2.7


【解决方案1】:

我建议,与其在此方法中捕获异常,不如让它引发异常并从您调用的任何位置捕获它。

换句话说,不要把你的 try catch 放在那个方法中。将 try catch 放在调用该方法的任何地方,然后捕获它可能引发的内容。

所以,改用这个:

import traceback

def ReadFile():
    with open("/etc/passwd") as file:
        data = file.read()
    return data

try:
    r = ReadFile()
except IOError:
    traceback.format_exc()
    # or log or whatever operation

或者,如果您真的想在该方法中处理您的异常并希望返回某种“失败”信号,那么您可能应该返回异常对象并查看它是否存在。

所以,您也可以这样做。引发时返回 Exception 对象,并在调用方法时检查它是否存在异常

def ReadFile():
    try:
        with open("/etc/passwd") as file:
            data = file.read()
    except IOError as exc:
        return exc
    return data

if isinstance(r, Exception):
    # do exception things here

不过,我会选择第一个选项。

【讨论】:

  • 由于所有的答案和 Ismail 的评论,我现在知道我不应该在我的函数内部捕获异常,而是在它之外捕获它。谢谢大家-不敢相信这没有发生在我身上。出于好奇,如果我确实返回了异常对象本身,有没有办法从中读取回溯信息?或者这不是它存储的东西?
  • format_exc() 为您提供回溯。阅读此内容,那里有更多信息可以为您提供有关如何实现所需目标的更多背景信息:stackoverflow.com/a/12539332/1832539
  • 酷 - 我只是想知道这是否可能 - 显然是 - 感谢链接。到目前为止,选项 1 对我来说效果很好 - 它大大简化了我的代码。
【解决方案2】:

异常已经“返回”到封闭范围,这就是异常首先存在的全部原因。

# See how simple this is?
def read_file():
    with open('/etc/passwd') as file:
        return file.read()

然后您在调用链中的适当位置处理异常,但在适当的位置。对于您希望以特定方式处理的预期异常,请在您有足够信息正确处理它们的地方处理它们。对于一般异常,在顶级事件循环中处理它们,或者简单地将它们向上传播并让解释器将它们打印出来。

与大多数其他事情一样,您希望处理异常的确切方式因程序而异。但是将异常作为函数结果返回会适得其反。

【讨论】:

    【解决方案3】:

    如果你想返回异常对象,你可以这样做:

    def ReadFile():
        try:
            with open("/etc/passwd") as file:
                data = file.read()
        except IOError as ex:
            return ex
        return data
    

    然而正如 Ismail 所说,最好让它抛出异常

    def ReadFile():
        with open("/etc/passwd") as file:
            return file.read()
    
    ... # Some code that eventually calls the function
    ...
    try:
        data = ReadFile()
    except IOError:
        print("File read failed")
        ... # Handle error
    

    【讨论】:

      猜你喜欢
      • 2013-06-03
      • 1970-01-01
      • 1970-01-01
      • 2022-12-09
      • 2020-03-15
      • 1970-01-01
      • 1970-01-01
      • 2013-12-16
      • 2022-12-22
      相关资源
      最近更新 更多