我使用以下代码调用具有适当数量参数的任意可调用f()
:
try:
res = f(arg1)
except TypeError:
res = f(arg1, arg2)
如果f()
是一个双参数函数,只用一个参数调用它就会引发TypeError
,因此可以在except
分支中正确调用该函数。
问题是当f()
是单参数函数且异常在f()
的主体中升级时(可能是因为对某个函数的调用不好),例如:
def f(arg):
map(arg) # raises TypeError
由于except
的内部错误,控制流进入f()
分支。当然,用两个参数调用f()
会引发一个新的TypeError
。然后我没有回溯到原始错误,而是使用两个参数追溯到f()
的调用,这在调试时没那么有用。
我的代码如何识别不在当前范围内引发的异常来重新加注它们?
我想写这样的代码:
try:
res = f(arg1)
except TypeError:
if exceptionRaisedNotInTheTryBlockScope(): # <-- subject of the question
raise
res = f(arg1, arg2)
我知道我可以在exc_info = sys.exc_info()
区块中添加except
来使用walkarround。
其中一个假设是我无法控制f()
,因为它是由我的模块的用户给出的。此外,__name__
属性可能不是'f'
。对f()
的错误重复调用可能会引发内部异常。
walkarround不合适,因为它使f()
的作者的调试变得复杂。
答案 0 :(得分:0)
您可以捕获异常对象并进行检查。
try:
res = f(arg1)
except TypeError as e:
if "f() missing 1 required positional argument" in e.args[0]:
res = f(arg1, arg2)
else:
raise
坦率地说,不要花费额外的长度来对异常进行分类应该可以正常工作,因为如果错误源自f(),你应该同时获得原始回溯和辅助回溯 - 调试应该不是问题。 / p>
另外,如果你可以控制f(),你可以选择第二个参数,而不必再猜测它:
def f(a, b=None):
pass
现在你可以用任何一种方式调用它。
这个怎么样:
import inspect
if len(inspect.getargspec(f).args) == 1:
res = f(arg1)
else:
res = f(arg1, arg2)
答案 1 :(得分:0)
终于明白了:
def exceptionRaisedNotInTheTryBlockScope():
return sys.exc_info()[2].tb_next is not None
sys.exc_info()
返回3个元素tuple
。它的最后一个元素是最后一个异常的回溯。如果回溯对象是回溯链中的唯一对象,则异常在try
块(https://docs.python.org/2/reference/datamodel.html)的范围内已经升级。
根据https://docs.python.org/2/library/sys.html#sys.exc_info,应该避免存储回溯值。