我正在编写一个基于main
函数的基本Python脚本,该脚本按顺序调用其他函数。
我想要做的是将main
中调用的所有函数包装起来:
result = func(*some_args):
if (result != True):
return result
例如,对于此代码:
def func1(arg1 , arg2):
if (some_cond):
return False #Or some err_val
return True
def func2(arg1):
if (some_cond):
return False
return True
def main():
func1(val1 , val2)
func2(val3)
return True
if __name__ == "__main__":
import sys
result = main()
if (result == err_val1):
# Do something. Maybe print. Maybe call some function.
sys.exit(1)
我希望如果其中一个函数失败main
会中断并返回其错误。我可以使用装饰器吗?
答案 0 :(得分:2)
我认为最好的解决方案是使用例外。如果这绝对不是你想要的,你可以做一些短路:
return func1() and func2()
将此扩展到更多功能,而不需要and
s:
from functools import partial
def main():
funcs = (partial(func1, arg1, arg2),
partial(func2, arg1))
if any(!f() for f in funcs):
return False
虽然这并没有返回"它的错误" (失败的函数错误),它只返回False
。如果你想在不同类型的错误之间做出更多区分......那么,你要回到例外。
答案 1 :(得分:2)
这正是在Python中构建的异常。
removeItem()
答案 2 :(得分:1)
由于你做实际上希望程序在发生其中一个错误时死亡,你也可以提升SystemExit
。这是使用装饰器完成此操作的方法。
flag = 2
def die_on_not_True(func):
def wrapper(*args):
rc = func(*args)
if rc is not True:
fmt = 'Function {} failed with return value {!r}'
print(fmt.format(func.__name__, rc))
raise SystemExit(1)
return True
return wrapper
@die_on_not_True
def func1(arg1 , arg2):
if arg1 == flag:
return 'error 1'
return True
@die_on_not_True
def func2(arg1):
if arg1 == flag:
return 'error 2'
return True
def main():
val1, val2, val3 = 1, 2, 3
print(func1(val1, val2))
print('one')
print(func2(val3))
print('two')
if __name__ == '__main__':
main()
<强>输出强>
True
one
True
two
如果我们设置flag = 1
,则输出变为
Function func1 failed with return value 'error 1'
如果我们设置flag = 3
,则输出变为
True
one
Function func2 failed with return value 'error 2'
当flag
等于2时,退出状态为0返回给shell,当flag
等于1或3时,退出状态为1。
如果您想在打印错误消息后进行进一步处理,请提出自定义异常而不是SystemExit
,并通过将main
来电包裹在try...except
中来抓住它。
答案 3 :(得分:0)
我想,你真正想要的是一个通用异常捕获器,它将捕获并返回任何包装函数的异常。你可以这样轻松地做到这一点。
def return_exception(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
return e
return wrapper
实施例
In [3]: @return_exception
...: def div(a, b):
...: return a / b
...:
In [4]: div(1, 0)
Out[4]: ZeroDivisionError('division by zero')
那么你可以按照你想要的方式处理返回异常对象,虽然很难说你为什么需要它。
更新正如其他人所说,仅捕获特定异常通常会很好。您可以稍微修改装饰器。
def return_exception(*exception_types):
def build_wrapper(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except exception_types as e:
return e
return wrapper
return build_wrapper
示例:
In [6]: @return_exception(ZeroDivisionError)
...: def div(a, b):
...: return a / b
...:
In [7]: div(0, 1)
Out[7]: 0.0
In [8]: div(1, 0)
Out[8]: ZeroDivisionError('division by zero')
In [9]: div(1, "a")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
...
TypeError: unsupported operand type(s) for /: 'int' and 'str'
In [10]: @return_exception(ZeroDivisionError, TypeError)
....: def div(a, b):
....: return a / b
....:
In [11]: div(1, 0)
Out[11]: ZeroDivisionError('division by zero')
In [12]: div(1, "a")
Out[12]: TypeError("unsupported operand type(s) for /: 'int' and 'str'")
如您所见,您只捕获指定的异常(但您仍然可以指定通用Exception
类。)