Python 当被调用程序中发生异常时,如何将异常返回给调用程序,该程序有自己的异常处理?

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

我正在python程序中循环一个列表。对于列表中的每个项目,我从当前程序中导入的不同python文件调用一个函数。具有被调用函数的文件有自己的异常处理。我希望调用程序在被调用程序中发生异常时跳过循环的当前迭代,并继续循环的下一次迭代。我尝试在调用程序的EXPECT子句中使用
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代码,但不能随意修改。不过,我可以对它做一些小的调整。是否有任何其他构造可以用于获取该行为