Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 展平嵌套的try/except子句_Python_Python 3.x - Fatal编程技术网

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真聪明!