Python 展平嵌套的try/except子句
我想在同一个任务中尝试多种不同的方法,在每次方法失败时捕获异常。我知道如果一次尝试失败将引发的异常(每次尝试都可能不同)。在最后一次尝试之后,我想优雅地放弃,继续前进 我目前通过嵌套的Python 展平嵌套的try/except子句,python,python-3.x,Python,Python 3.x,我想在同一个任务中尝试多种不同的方法,在每次方法失败时捕获异常。我知道如果一次尝试失败将引发的异常(每次尝试都可能不同)。在最后一次尝试之后,我想优雅地放弃,继续前进 我目前通过嵌套的try/来实现这一点,除了子句: try: first_approach() except Exception1: try: second_approach() except Exception2: try: third_approac
try
/来实现这一点,除了
子句:
try:
first_approach()
except Exception1:
try:
second_approach()
except Exception2:
try:
third_approach()
except:
give_up()
except Exception2:
try:
third_approach()
except:
give_up()
但这对我来说很糟糕,因为第三种方法是重复的。在这方面我看不到任何帮助。
那么,我如何才能扁平化这个丑陋的嵌套代码呢
一个具体的例子
例如,假设我试图读取CSV文件列表,而事先不知道它们的编码
一些CSV文件甚至可能是XLS文件,通过其文件扩展名伪装成CSV
因此,我想尝试几种不同的编码,如果这些编码都不起作用,请尝试将文件读取为excel
for f in files:
try:
read_csv(f, encoding='utf-8')
except UnicodeDecodeError:
try:
read_csv(f, encoding='latin1')
except NotCsvError:
try:
read_excel(f)
except:
give_up()
except NotCsvError:
try:
read_excel(f)
except:
give_up()
仍然嵌套,但已干燥:
for f in files:
try:
try:
read_csv(f, encoding='utf-8')
except UnicodeDecodeError:
read_csv(f, encoding='latin1')
except NotCsvError:
try:
read_excel(f)
except:
give_up()
在外部块中,首先尝试使用UTF-8,然后使用拉丁语-1,如果失败,则使用UnicodeDecodeError。如果其中任何一个失败并出现NotCsvError,则控制权将传递到外部
except
子句。这利用了这样一个事实,即read\u excel
不关心您以前尝试过的编码。您可以使用for
/else
循环来循环您的方法函数
只有当break
语句未终止for
时,else
子句才会运行
approaches = ((first_approach, [arg1, arg2, ...], {'kwarg1':kwarg1, 'kwarg2':kwarg2, ...}, (Approach1Exception1, Approach1Exception2, ...)),
(second_approach, ..., ..., ...),
(third_approach, ..., ..., ...),
...)
for approach, args, kwargs, exceptions in approaches:
try:
approach(*args, **kwargs)
break
except exceptions:
pass
else:
give_up()
虽然在我的解决方案中仍然存在三个嵌套级别,但尝试不同方法的逻辑已变得平淡:
ex = None
while True:
try:
if ex is None:
first_approach()
elif ex is Exception1:
second_approach()
elif ex is Exception2:
third_approach()
else:
give_up()
break
except:
ex = sys.exc_info()[0]
但是,请注意,此代码并不是100%等同于您的版本。例如,如果
third_approach()
引发Exception2
否则没有if?@Rahul yes,它将结束为一个无限循环。如果break
语句未终止for
循环,则执行else
块。OK。非常感谢。您还可以将“允许的异常”作为元组放在方法中,然后对于每种方法,除了允许的异常
,这样您就不会捕获所有方法中所有可能的异常…@JonClements真聪明!