Python 当被调用程序中发生异常时,如何将异常返回给调用程序,该程序有自己的异常处理?
我正在python程序中循环一个列表。对于列表中的每个项目,我从当前程序中导入的不同python文件调用一个函数。具有被调用函数的文件有自己的异常处理。我希望调用程序在被调用程序中发生异常时跳过循环的当前迭代,并继续循环的下一次迭代。我尝试在调用程序的EXPECT子句中使用Python 当被调用程序中发生异常时,如何将异常返回给调用程序,该程序有自己的异常处理?,python,exception-handling,Python,Exception Handling,我正在python程序中循环一个列表。对于列表中的每个项目,我从当前程序中导入的不同python文件调用一个函数。具有被调用函数的文件有自己的异常处理。我希望调用程序在被调用程序中发生异常时跳过循环的当前迭代,并继续循环的下一次迭代。我尝试在调用程序的EXPECT子句中使用continue关键字。但它没有像我预期的那样工作 程序的结构是这样的- A.py import B for item in list: try : B.some_function(item) e
continue
关键字。但它没有像我预期的那样工作
程序的结构是这样的-
A.py
import B
for item in list:
try :
B.some_function(item)
except Exception as err:
continue
from B import some_function , MyException
lst = [0,2,4,1,3] # for example take it as list of number
for item in lst:
try :
some_function(item)
except MyException as err:
print "error"
continue
class MyException(Exception):
pass
def some_function(val):
""" this function raise exception when val equal to 1 """
if val == 1: # for example raise exception when input is 1
raise MyException
else:
print val
#exception handling toggles this flag
exception_handled = False
def f():...
def g():...
...
import B
for item in list:
try :
B.some_function(item)
if B.exception_handled:
#reset flag
B.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.exception_handled = False
continue
#decorator to add flag to functions
def add_attr(func):
func.exception_handled = False
return func
@add_attr
def f():...
@add_attr
def g():...
...
#exception handler modifies a function attribute
#func.exception_handled = True
import B
for item in list:
try :
B.some_function(item)
if B.some_function.exception_handled:
# reset flag
B.some_function.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.some_function.exception_handled = False
continue
exceptions = {}
def register(func):
exceptions[func.__name__] = False
return func
@register
def f():...
@register
def g():...
#exception handling -> exceptions[f] = True or exceptions[current_func] = True
请注意,文件B.py包含几个具有自己异常处理的函数。当第一个异常发生时,上述代码将终止。我希望它继续循环的下一个迭代
为什么会发生这种情况?如果B.某些函数(项)
从未引发一个异常,那么try
块就没有意义了。
您将永远无法捕捉到B.某些功能执行时出现的任何故障。
因此,您需要B.一些函数
来实际引发错误。
那么,“为什么会发生这种情况”?只是因为“[某些函数
]有自己的异常处理”
如果您有权访问它的代码,您应该编辑它,以便它在需要时实际引发错误
如果您无法访问其代码,则有两种可能:
该功能的设计可以检测到错误或故障。在需要时引发(且未捕获)错误,或者函数的返回值告知操作是否有效或失败李>
该功能的设计使其不会出现任何错误,也不会检测到任何故障
如果是1,好的,你需要做的就是找到并理解如何检测错误。
如果它是2,那么,您不能(同样,假设您不能编辑代码)。
如果是这样,函数的使用方式可能与您尝试使用它的方式不同
由于您确实有权对某些函数
进行细微更改,因此这里有一个修复程序,它不应破坏依赖它的任何代码,同时允许您检查是否发生错误
"""A.py"""
class MyFlag:
def __init__(self):
self.value = False
# Just for more comfort: allows to write "if myFlag: ..."
def __bool__(self):
return self.value
# Create a flag that will be down unless an error was raised
errorCaught = MyFlag()
# Call some_function and pass the flag as myFlag keyword argument
B.some_function(arguments.., myFlag=errorCaught)
# If errorCaught is True, then errorCaught.value is True as well,
# hence an error was detected
if errorCaught:
print("An error got raised")
首先,将关键字参数添加到B.some_函数
,该函数默认为None
。
这样,任何调用它的代码都不会中断,因为它将在没有显式传递的情况下被设置。
此参数将作为一个标志:如果引发,则发生错误。
这里,“raised”表示其内部值设置为True
。
如果没有标志作为参数传递,则行为保持不变
"""B.py"""
def some_function(arguments..., myFlag=None):
# stuff
if error_happens():
if myFlag is not None:
myFlag.value = True
# stuff
现在,在A.py
中定义一个标志类。
不能使用简单的布尔值,因为它需要通过引用传递给B.some_函数
,并由它修改。
MyFlag
实例有一个value
属性,该属性在初始化时设置为False
,当标志需要指示发生了什么事情时,该属性将设置为True
"""A.py"""
class MyFlag:
def __init__(self):
self.value = False
# Just for more comfort: allows to write "if myFlag: ..."
def __bool__(self):
return self.value
# Create a flag that will be down unless an error was raised
errorCaught = MyFlag()
# Call some_function and pass the flag as myFlag keyword argument
B.some_function(arguments.., myFlag=errorCaught)
# If errorCaught is True, then errorCaught.value is True as well,
# hence an error was detected
if errorCaught:
print("An error got raised")
在下面的示例中,我在模块B.py中定义了一个自定义异常MyException,并在函数中提出了一些函数。在模块A.py中,我使用try-and-catch-over调用b.py模块的some_函数
A.py
import B
for item in list:
try :
B.some_function(item)
except Exception as err:
continue
from B import some_function , MyException
lst = [0,2,4,1,3] # for example take it as list of number
for item in lst:
try :
some_function(item)
except MyException as err:
print "error"
continue
class MyException(Exception):
pass
def some_function(val):
""" this function raise exception when val equal to 1 """
if val == 1: # for example raise exception when input is 1
raise MyException
else:
print val
#exception handling toggles this flag
exception_handled = False
def f():...
def g():...
...
import B
for item in list:
try :
B.some_function(item)
if B.exception_handled:
#reset flag
B.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.exception_handled = False
continue
#decorator to add flag to functions
def add_attr(func):
func.exception_handled = False
return func
@add_attr
def f():...
@add_attr
def g():...
...
#exception handler modifies a function attribute
#func.exception_handled = True
import B
for item in list:
try :
B.some_function(item)
if B.some_function.exception_handled:
# reset flag
B.some_function.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.some_function.exception_handled = False
continue
exceptions = {}
def register(func):
exceptions[func.__name__] = False
return func
@register
def f():...
@register
def g():...
#exception handling -> exceptions[f] = True or exceptions[current_func] = True
B.py
import B
for item in list:
try :
B.some_function(item)
except Exception as err:
continue
from B import some_function , MyException
lst = [0,2,4,1,3] # for example take it as list of number
for item in lst:
try :
some_function(item)
except MyException as err:
print "error"
continue
class MyException(Exception):
pass
def some_function(val):
""" this function raise exception when val equal to 1 """
if val == 1: # for example raise exception when input is 1
raise MyException
else:
print val
#exception handling toggles this flag
exception_handled = False
def f():...
def g():...
...
import B
for item in list:
try :
B.some_function(item)
if B.exception_handled:
#reset flag
B.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.exception_handled = False
continue
#decorator to add flag to functions
def add_attr(func):
func.exception_handled = False
return func
@add_attr
def f():...
@add_attr
def g():...
...
#exception handler modifies a function attribute
#func.exception_handled = True
import B
for item in list:
try :
B.some_function(item)
if B.some_function.exception_handled:
# reset flag
B.some_function.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.some_function.exception_handled = False
continue
exceptions = {}
def register(func):
exceptions[func.__name__] = False
return func
@register
def f():...
@register
def g():...
#exception handling -> exceptions[f] = True or exceptions[current_func] = True
输出
0
2
4
error
3
听起来您需要在A
和B
之间发送一些额外的信号。它需要是对B
的透明添加,不会干扰其当前行为。基本上是向B
的范围添加一些内容,这些内容可以通过异常处理进行修改,也可以通过A
进行查询
根据B
中的其他内容,我认为模块级变量用作标记,表示B
中的try/except可以更改,而a
中的try/except可以查询
B.py
import B
for item in list:
try :
B.some_function(item)
except Exception as err:
continue
from B import some_function , MyException
lst = [0,2,4,1,3] # for example take it as list of number
for item in lst:
try :
some_function(item)
except MyException as err:
print "error"
continue
class MyException(Exception):
pass
def some_function(val):
""" this function raise exception when val equal to 1 """
if val == 1: # for example raise exception when input is 1
raise MyException
else:
print val
#exception handling toggles this flag
exception_handled = False
def f():...
def g():...
...
import B
for item in list:
try :
B.some_function(item)
if B.exception_handled:
#reset flag
B.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.exception_handled = False
continue
#decorator to add flag to functions
def add_attr(func):
func.exception_handled = False
return func
@add_attr
def f():...
@add_attr
def g():...
...
#exception handler modifies a function attribute
#func.exception_handled = True
import B
for item in list:
try :
B.some_function(item)
if B.some_function.exception_handled:
# reset flag
B.some_function.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.some_function.exception_handled = False
continue
exceptions = {}
def register(func):
exceptions[func.__name__] = False
return func
@register
def f():...
@register
def g():...
#exception handling -> exceptions[f] = True or exceptions[current_func] = True
A.py
import B
for item in list:
try :
B.some_function(item)
except Exception as err:
continue
from B import some_function , MyException
lst = [0,2,4,1,3] # for example take it as list of number
for item in lst:
try :
some_function(item)
except MyException as err:
print "error"
continue
class MyException(Exception):
pass
def some_function(val):
""" this function raise exception when val equal to 1 """
if val == 1: # for example raise exception when input is 1
raise MyException
else:
print val
#exception handling toggles this flag
exception_handled = False
def f():...
def g():...
...
import B
for item in list:
try :
B.some_function(item)
if B.exception_handled:
#reset flag
B.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.exception_handled = False
continue
#decorator to add flag to functions
def add_attr(func):
func.exception_handled = False
return func
@add_attr
def f():...
@add_attr
def g():...
...
#exception handler modifies a function attribute
#func.exception_handled = True
import B
for item in list:
try :
B.some_function(item)
if B.some_function.exception_handled:
# reset flag
B.some_function.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.some_function.exception_handled = False
continue
exceptions = {}
def register(func):
exceptions[func.__name__] = False
return func
@register
def f():...
@register
def g():...
#exception handling -> exceptions[f] = True or exceptions[current_func] = True
或者,您可以向异常处理可以切换的B
函数添加属性/标志,A
可以查询
B.py
import B
for item in list:
try :
B.some_function(item)
except Exception as err:
continue
from B import some_function , MyException
lst = [0,2,4,1,3] # for example take it as list of number
for item in lst:
try :
some_function(item)
except MyException as err:
print "error"
continue
class MyException(Exception):
pass
def some_function(val):
""" this function raise exception when val equal to 1 """
if val == 1: # for example raise exception when input is 1
raise MyException
else:
print val
#exception handling toggles this flag
exception_handled = False
def f():...
def g():...
...
import B
for item in list:
try :
B.some_function(item)
if B.exception_handled:
#reset flag
B.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.exception_handled = False
continue
#decorator to add flag to functions
def add_attr(func):
func.exception_handled = False
return func
@add_attr
def f():...
@add_attr
def g():...
...
#exception handler modifies a function attribute
#func.exception_handled = True
import B
for item in list:
try :
B.some_function(item)
if B.some_function.exception_handled:
# reset flag
B.some_function.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.some_function.exception_handled = False
continue
exceptions = {}
def register(func):
exceptions[func.__name__] = False
return func
@register
def f():...
@register
def g():...
#exception handling -> exceptions[f] = True or exceptions[current_func] = True
A.py
import B
for item in list:
try :
B.some_function(item)
except Exception as err:
continue
from B import some_function , MyException
lst = [0,2,4,1,3] # for example take it as list of number
for item in lst:
try :
some_function(item)
except MyException as err:
print "error"
continue
class MyException(Exception):
pass
def some_function(val):
""" this function raise exception when val equal to 1 """
if val == 1: # for example raise exception when input is 1
raise MyException
else:
print val
#exception handling toggles this flag
exception_handled = False
def f():...
def g():...
...
import B
for item in list:
try :
B.some_function(item)
if B.exception_handled:
#reset flag
B.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.exception_handled = False
continue
#decorator to add flag to functions
def add_attr(func):
func.exception_handled = False
return func
@add_attr
def f():...
@add_attr
def g():...
...
#exception handler modifies a function attribute
#func.exception_handled = True
import B
for item in list:
try :
B.some_function(item)
if B.some_function.exception_handled:
# reset flag
B.some_function.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.some_function.exception_handled = False
continue
exceptions = {}
def register(func):
exceptions[func.__name__] = False
return func
@register
def f():...
@register
def g():...
#exception handling -> exceptions[f] = True or exceptions[current_func] = True
我想它会变得更复杂,就像
B
中的模块级字典,保存每个B
函数的状态
B.py
import B
for item in list:
try :
B.some_function(item)
except Exception as err:
continue
from B import some_function , MyException
lst = [0,2,4,1,3] # for example take it as list of number
for item in lst:
try :
some_function(item)
except MyException as err:
print "error"
continue
class MyException(Exception):
pass
def some_function(val):
""" this function raise exception when val equal to 1 """
if val == 1: # for example raise exception when input is 1
raise MyException
else:
print val
#exception handling toggles this flag
exception_handled = False
def f():...
def g():...
...
import B
for item in list:
try :
B.some_function(item)
if B.exception_handled:
#reset flag
B.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.exception_handled = False
continue
#decorator to add flag to functions
def add_attr(func):
func.exception_handled = False
return func
@add_attr
def f():...
@add_attr
def g():...
...
#exception handler modifies a function attribute
#func.exception_handled = True
import B
for item in list:
try :
B.some_function(item)
if B.some_function.exception_handled:
# reset flag
B.some_function.exception_handled = False
raise Exception
# or just
#continue
except Exception as err:
B.some_function.exception_handled = False
continue
exceptions = {}
def register(func):
exceptions[func.__name__] = False
return func
@register
def f():...
@register
def g():...
#exception handling -> exceptions[f] = True or exceptions[current_func] = True
然后A
查询字典:
if any(B.exceptions.values()):
#reset the flags
for k in B.exceptions:
B.exceptions[k] = False
#raise exception
#just continue
对于最后两种解决方案,您可以使用sys、traceback和/或inspect模块确定函数名。获得名称后,可以根据需要通过globals()或locals()获取对函数本身的引用。下面是一个关于B.py
中内容的快速示例
from pprint import pprint
import sys, inspect, traceback
exceptions = {}
def g():
try:
return 1 / 0
except ZeroDivisionError as e:
#find the function name as a string from the traceback
typ, val, tb = sys.exc_info()
# one way
func_name0 = traceback.extract_tb(tb)[-1][-2]
# another way via the frame object:
# you have to get to the frame that caused the exception
tb_x = tb
while tb_x.tb_next is not None:
tb_x = tb_x.tb_next
func_name1 = tb_x.tb_frame.f_code.co_name
print func_name0, func_name1
# toggle the exeptions dictionary
exceptions[func_name0] = True
# get a reference to the function after finding the name
func = globals()[func_name0]
# and toggle its flag attribute
func.exception_handled = True
# what can you do with inspect
# inspect.trace()[-1] contains the same frame object as tb_x
pprint(inspect.trace()[-1])
func_name2 = inspect.trace()[-1][-3]
从2.7代码的print语句中可以看出,这台机器上没有3.x。在3.x中,有一些新的方法用于回溯和检查模块,这些方法可能很有用。您的代码实际上应该可以工作。您确定您的列表中有多个项目吗?您不应捕获异常,而应捕获预期会发生的显式异常(例如ValueError
)。实际上,您不需要使用continue
,只需使用pass
。B中的函数是否返回任何内容?这是预期的行为,因为您确实在B中处理异常。some_函数(项)
调用,因此除非B.some_函数(项),否则您永远不会掉到块之外
引发未处理的异常。是的,这是我最初的想法。程序B自行处理异常,因此调用程序A无法检测到异常。我有权使用B代码,但不能随意修改。不过,我可以对它做一些小的调整。是否有任何其他构造可以用于获取该行为