在 Python 异常处理程序中捕获异常的更简洁方法

id0*_*d01 2 python exception

在 Python 程序中,通常使用 try-except 块捕获异常:

try:
    # Do stuff
except ValueError:
    # Handle exception
Run Code Online (Sandbox Code Playgroud)

据我所知,在异常处理程序中捕获异常的最佳方法是嵌套的 try-except 块。然而,对于许多嵌套的 try-catch 块,这可能会变得有点混乱:

try:
    # Some assignment that throws an exception if the object is not in the list
    try:
        # Some assignment function that throws an exception if the the object is not already in the database
        # Error Handling
    except ValueError:
        try:
            # Some function that throws an exception if the object does not have an undesired property
            # Error Handling
        except AttributeError:
            try:
                # Some function that throws an exception if an error happens
            except Exception:
                # Exception handling
except ValueError:
    # Exception handling
Run Code Online (Sandbox Code Playgroud)

有没有更简洁的方法来做到这一点?就像是:

try:
   # Some assignment that throws an exception if the object is not in the list
   try:
       # Some assignment function that throws an exception if the object is not already in the database
   except ValueError:
       # Some function that throws an exception if the object does not have an undesired property
   exceptexcept AttributeError:
       # Some function that throws an exception if an error happens
   exceptexcept Exception:
       # Exception handling 
except ValueError:
   # Exception handling
Run Code Online (Sandbox Code Playgroud)

Mat*_*ipp 5

这听起来像是一个循环,你想继续尝试,直到成功或用尽选择。所以你可以这样实现它,例如,像这样

# Each pair contains a function to call and an exception that can be caught.
# If that exception is raised, the next function will be tried.
action_list = [
    (get_from_list, ValueError),  # throws ValueError if item can't be retrieved
    (get_from_database, ValueError),  # throws ValueError if item can't be retrieved
    (get_from_object, AttributeError),  # throws AttributeError if item lacks desired property
]

result = None
for action, ex in action_list:
    try:
        result = action(key)
        break
    except ex:
        continue
Run Code Online (Sandbox Code Playgroud)

您可以通过让所有辅助函数引发一个自定义异常(例如“NotFound”)来稍微整理一下,然后将其用作检查下一个级别的信号,如下所示:

# actions to try; all raise NotFound if unsuccessful
action_list = [
    get_from_list, get_from_database, get_from_object
]

result = None
for action in action_list:
    try:
        result = action(key)
        break
    except NotFound:
        continue
Run Code Online (Sandbox Code Playgroud)

或者您可以将所有步骤放入一个函数中,该函数一旦成功就返回。这样您的分配就可以用常规代码完成,而不是使用辅助函数:

def get_value(key):

    try:
        return some_list[int(key)]
    except ValueError:
        pass

    try:
        return get_from_database(key)
    except ValueError:
        pass

    try:
        return getattr(some_object, key)
    except AttributeError:
        pass

    return None
Run Code Online (Sandbox Code Playgroud)

如果你不想要另一个函数,你可以滥用for循环:

result = None
for _ in range(1):

    try:
        result = some_list[int(key)]
        break
    except ValueError:
        pass

    try:
        result = get_from_database(key)
        break
    except ValueError:
        pass

    try:
        result = getattr(some_object, key)
        break
    except AttributeError:
        pass
Run Code Online (Sandbox Code Playgroud)

或者您可以使用单个外部try/except和自定义Found异常作为“结构化 goto ”:

result = None
try:
    try:
        result = some_list[int(key)]
        raise Found
    except ValueError:
        pass
    try:
        result = get_from_database(key)
        raise Found
    except ValueError:
        pass
    try:
        result = getattr(some_object, key)
        raise Found
    except AttributeError:
        pass
except Found:
    pass  # all good
Run Code Online (Sandbox Code Playgroud)

或者有一个经过尝试但真实的构造:

result = None
if result is None:
    try:
        result = some_list[int(key)]
    except ValueError:
        pass
if result is None:
    try:
        result = get_from_database(key)
    except ValueError:
        pass
if result is None:
    try:
        result = getattr(some_object, key)
    except AttributeError:
        pass
Run Code Online (Sandbox Code Playgroud)