在Python程序中,通常使用try-except 块捕获异常:
try:
# Do stuff
except ValueError:
# Handle exception
据我所知,在异常处理程序中捕获异常的最佳方法是嵌套的 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
有没有更整洁的方法可以做到这一点?像这样:
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
这听起来像是一个循环,你想继续尝试,直到你成功或用完选择。所以你可以这样实现它,例如,像这样的东西
# 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
您可以通过让所有帮助程序函数引发自定义异常(如"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
或者,您可以将所有步骤放在一个函数中,该函数在成功后立即返回。这样,您的赋值可以在常规代码中完成,而不是使用帮助程序函数:
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
如果你不想要另一个函数,你可以滥用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
或者,您可以使用带有自定义Found
例外的单个外部try
/except
作为"结构化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
或者有这个久经考验但真实的结构:
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