Smooth try / except nested arguments

I want to try several different approaches in the same task, catching exceptions every time the approach fails. I know an exception that will be raised if the attempt fails (and it may be different for each attempt). After the last attempt, I want to gracefully refuse and move on.

I am currently doing this through nested try/ exceptsuggestions:

try:
    first_approach()
except Exception1:
    try:
        second_approach()
    except Exception2:
        try:
            third_approach()
        except:
            give_up()
except Exception2:
    try:
        third_approach()
    except:
        give_up()

But it looks bad to me because it third_approach()repeats itself. I don't see any help for this in Python docs . So how can I smooth out this ugly nested code?

Specific example

For example, imagine that I am trying to read a list of CSV files without knowing their encoding in advance.

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()
+4
3

for/else.

else , for break.

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()
+7

- , DRYer:

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_excel , .

+2

Although there are still three levels of nesting in my solution, the logic of the different approaches is smoothed out:

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]

Please note, however, that this code is not 100% equivalent to your version. For example, it will end as an endless loop if third_approach()called Exception2.

0
source

Source: https://habr.com/ru/post/1683242/


All Articles