How to write multiple try statements in one block in python?

33,202

Solution 1

I'd write a quick wrapper function first() for this.

usage: value = first([f1, f2, f3, ..., fn], default='All failed')

#!/usr/bin/env


def first(flist, default=None):

    """ Try each function in `flist` until one does not throw an exception, and
    return the return value of that function. If all functions throw exceptions,
    return `default` 

    Args: 
        flist - list of functions to try
        default - value to return if all functions fail

    Returns:
        return value of first function that does not throw exception, or
        `default` if all throw exceptions.

    TODO: Also accept a list of (f, (exceptions)) tuples, where f is the
    function as above and (exceptions) is a tuple of exceptions that f should
    expect. This allows you to still re-raise unexpected exceptions.
    """

    for f in flist:
        try:
            return f()
        except:
            continue
    else:
        return default

# Testing.

def f():
    raise TypeError

def g():
    raise IndexError

def h():
    return 1


# We skip two exception-throwing functions and return value of the last.
assert first([f, g, h]) == 1

assert first([f, g, f], default='monty') == 'monty'

Solution 2

If you really don't care about the exceptions, you could loop over cases until you succeed:

for fn in (do, do2, do3, do4):
    try:
        fn()
        break
    except:
        continue

This at least avoids having to indent once for every case. If the different functions need different arguments you can use functools.partial to 'prime' them before the loop.

Solution 3

It seems like a really odd thing to want to do, but I would probably loop over the functions and break out when there were no exception raised:

for func in [do, do2, do3]:
    try:
        func()
    except Exception:
        pass
    else:
        break 

Solution 4

Here is the simplest way I found, just embed the try under the previous except.

try:
    do()
except:
    try:
        do2()
    except:
        do3()

Solution 5

You should specify the type of the exception you are trying to catch each time.

try:
    do()
except TypeError: #for example first one - TypeError
    do_2()
except KeyError: #for example second one - KeyError
    do_3()

and so on.

Share:
33,202
alwbtc
Author by

alwbtc

Updated on July 09, 2022

Comments

  • alwbtc
    alwbtc almost 2 years

    I want to do:

    try:
        do()
    except:
        do2()
    except:
        do3()
    except:
        do4()
    

    If do() fails, execute do2(), if do2() fails too, exceute do3() and so on.

    best Regards

  • alwbtc
    alwbtc over 11 years
    If I don't know the type of the exception?
  • BrenBarn
    BrenBarn over 11 years
    @alwbic: If you don't know the type of the exception, you don't know how to handle the exception.
  • alexvassel
    alexvassel over 11 years
    @alwbic I am really sure that you must know what type(s) of exception(s) do you expect.
  • alwbtc
    alwbtc over 11 years
    I don't agree with you. I know that my statement will fail, but i don't know in which order they will fail. But I know what to do if it fails.
  • alexvassel
    alexvassel over 11 years
    @alwbic: It is just a bad practice "Do something if something fails", you don't now why it fails.
  • Kenan Banks
    Kenan Banks over 11 years
    pass should be continue perhaps? Works as written but continue is semantically clearer.
  • Fredrik Håård
    Fredrik Håård over 11 years
    @Triptych True, that does signal intent better. Edited answer.
  • Thierry Lathuille
    Thierry Lathuille almost 7 years
    This doesn't answer the question at all!
  • AbstProcDo
    AbstProcDo over 5 years
    Creat, but what's else here for? it seem redundant here.
  • gaqzi
    gaqzi over 5 years
    The else will only execute when there isn't an exception. If there's an exception the for will continue whereas if there wasn't an exception the break will execute. :) A lot of statements in Python takes an else with the intention of "if everything went well, then do this". See the documentation for the try statement: docs.python.org/3/reference/compound_stmts.html#try
  • Aaron John Sabu
    Aaron John Sabu almost 4 years
    I did the same thing but can't it be made more compact?
  • aerijman
    aerijman almost 4 years
    @alwbic. I agree with you and you can do except Exception: pass. Something I always do when I develop is except Exception as e: print(str(e)) to know what was the error.
  • Chris
    Chris over 2 years
    I laughed so hard at this answer, thanks for making my day