如何返回值并引发异常

Posted

技术标签:

【中文标题】如何返回值并引发异常【英文标题】:How to return a value and raise an Exception 【发布时间】:2014-02-10 09:10:30 【问题描述】:

我对这个try/except 声明有两个目标。

    如果没有发生问题,它需要return 值 1,如果发生任何问题,则需要 0。 需要引发异常并结束脚本。

我的return 值有效。我也有SystemExit() 工作。但是在一起,它们不起作用。

我的 Python 脚本(相关):

except IOError:
    value_to_return = 0
    return value_to_return
    raise SystemExit("FOOBAR")

这样,它会完全忽略raise SystemExit("FOOBAR") 行。如何获得返回值并且仍然是raise SystemExit("FOOBAR")?这对某些人来说可能是初级的,但实际上我在这方面遇到了很多困难。

【问题讨论】:

如果你提出 SystemExit 并且实际上希望你的脚本结束,返回值应该去哪里(脚本毕竟结束了)?还是先捕获异常,返回,做一些错误处理,然后退出? 如果你回来,加薪就不会发生。无论如何,你不能两者都做!选择你想要的,退出或返回。 只是猜测,但您可能需要返回 0 并让 调用者 提高 SystemExit。无法在同一个函数中同时执行这两种操作。 您是否要向外壳返回状态码? 我与首席工程师再次核对。他想要的是我的脚本返回一个 0,因为出现了问题,并且脚本应该结束,因为从那时起它就变得无用了。所以我确实需要返回一个 0 并结束脚本。我尝试了以下所有其他答案,均未奏效。 【参考方案1】:

我认为您可能正在寻找更像这样的东西:

def some_function():
    # this function should probably do some stuff, then return 1 if
    # it was successful or 0 otherwise.
    pass

def calling_function():
    a = some_function()
    if a == 1:
        raise SystemExit('Get the heck outta here!')
    else:
        # Everything worked!
        pass

【讨论】:

【参考方案2】:

归与养是互斥的。

提高SystemExit 将结束脚本。一些清理例程开始运行,如果调用者真的非常想要,他们可以捕获SystemExit 并取消它,但大多数情况下,您可以将其视为在此处停止执行。调用者永远不会有机会看到返回值或用它做任何有意义的事情。

返回意味着您希望脚本继续。继续可能意味着让调用者提出SystemExit,或者它可能意味着忽略错误,或者它可能意味着其他东西。这意味着什么取决于您,因为您是编写代码的人。

最后,你确定你应该处理这个错误吗?仅捕获异常以将其转换为系统关闭可能不是最有用的行为。这不是一种用户友好的问题处理方式,而且它隐藏了您从堆栈跟踪中获得的所有有用的调试信息。

【讨论】:

@ingyhere:不,教程部分很烂。 IIRC 有人从 Github 评论中复制了一个写得很糟糕的描述,而没有仔细检查它。 finally 将暂停异常的传播,然后return 将取消异常并返回"value" language reference 有更准确的描述,特别是“如果 finally 子句执行 return 或 break 语句,则丢弃保存的异常”。语言参考往往比教程好(但语言参考也不完美;例如,它经常没有提到如何通过魔术方法自定义各种操作)。 好的,@user2357112supportsMonica。我运行了一个示例程序,您确实是正确的。 Python.org link I presented above 不幸地逐字声明,“如果异常没有由 except 子句处理,则在 finally 子句执行后重新引发异常。”它还讨论了一个执行 finally 然后异常的示例。不过,这不一定与您写的内容相矛盾。不幸的是,在其他 SO 帖子中存在矛盾。为清楚起见,删除了之前的评论。【参考方案3】:

要退出脚本并返回退出状态,请使用sys.exit()

import sys
sys.exit(value_to_return)

【讨论】:

你不能也用__builtins__.exit(value_to_return)吗? @UltimateCreeper 是的,看起来是这样。 sys.exit 显然是程序中的首选,请参阅***.com/questions/6501121/…【参考方案4】:

你不能同时“raise”和“return”,所以你必须在返回值中添加一个特殊的变量(例如:在元组中)以防出错。

例如: 我有一个函数(名为“func”),它计算一些东西,即使在计算过程中发生异常,我也需要(部分)结果。在我的示例中,我将使用 KeyboardInterrupt 异常(用户按下 CTRL-C)。

函数中没有异常处理(这是错误的,万一出现异常函数不返回任何东西):

def func():
    s=0
    for i in range(10):
        s=s+1
        time.sleep(0.1)
    return s


x=0
try:
    for i in range(10):
       s=func()
       x=x+s
except KeyboardInterrupt:
    print(x)
else:
    print(x)

现在我引入一个布尔返回值(在元组中,在原始返回值旁边)来指示是否发生了异常。因为在函数中我只处理了 KeyboardInterrupt 异常,我可以肯定这已经发生了,所以我可以在调用函数的地方提出同样的问题:

def func():
    try:
        s=0
        for i in range(10):
            s=s+1
            time.sleep(0.1)
    except KeyboardInterrupt: # <- the trick is here
        return s, True        # <- the trick is here
    return s, False           # <- the trick is here


x=0
try:
    for i in range(10):
        s,e=func()
        x=x+s
        if e:                         # <- and here
            raise KeyboardInterrupt   # <- and here
except KeyboardInterrupt:
    print(x)
else:
    print(x)

注意:我的例子是 python3。使用了 time 模块(在上面的两个代码中),但我没有导入它只是为了让它更短。如果你想真正尝试一下,请放在开头:

import time

【讨论】:

【参考方案5】:

您可以在调用后使用“returning_value”参数引发错误。

对您的问题的另一个 Pythonic 答案可能是使用 raise 中的错误参数,然后在您的调用中管理错误以获取值,将其从字符串转换并获取您的“return-ish”。

def your_f():
    try:
      some_io_thingy_ok()
      return 1
    except IOError:
        raise SystemExit("FOOBAR", 0)

try:
    my_returning_value = your_f()
except SystemExit as err:
    my_returning_value = err.args[1]


print(my_returning_value)

来自Python 3 docs:

当异常发生时,它可能有一个关联的值,也称为 作为异常的论点。论据的存在和类型 取决于异常类型。

except 子句可以在异常名称之后指定一个变量。这 变量绑定到一个异常实例,并存储了参数 在 instance.args 中。为方便起见,异常实例定义 str(),因此可以直接打印参数,而无需引用 .args。也可以先实例化一个异常 提升它并根据需要为其添加任何属性。

【讨论】:

【参考方案6】:

我在不使用 try 的情况下寻找答案,像这样使用“finally”关键字。如果有人知道,请填写我 这是您问题的答案

try:
    9/0#sample error "don't know how to make IOError"
except ZeroDivisionError:
    value_to_return = 0
    raise SystemExit("FOOBAR")
finally:return value_to_return

【讨论】:

以上是关于如何返回值并引发异常的主要内容,如果未能解决你的问题,请参考以下文章

如何输入布尔值并作为布尔值返回?

shell 脚本 变量 获取程序输出结果异常分析

如何从exe获取返回值并重新启动它

如何从整数中删除最小值并在不使用字符串的情况下返回其余数字[关闭]

Finally-操作返回值

Emgu.CV.CvInvoke的类型初始值设定项引发异常如何解决 开发环境是VS2010