[python] Are nested try/except blocks in Python a good programming practice?

I'm writing my own container, which needs to give access to a dictionary inside by attribute calls. The typical use of the container would be like this:

dict_container = DictContainer()
dict_container['foo'] = bar
...
print dict_container.foo

I know that it might be stupid to write something like this, but that's the functionality I need to provide. I was thinking about implementing this in a following way:

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        try:
            return self.dict[item]
        except KeyError:
            print "The object doesn't have such attribute"

I'm not sure whether nested try/except blocks are a good practice, so another way would be to use hasattr() and has_key():

def __getattribute__(self, item):
        if hasattr(self, item):
            return object.__getattribute__(item)
        else:
            if self.dict.has_key(item):
                return self.dict[item]
            else:
                raise AttributeError("some customised error")

Or to use one of them and one try catch block like this:

def __getattribute__(self, item):
    if hasattr(self, item):
        return object.__getattribute__(item)
    else:
        try:
            return self.dict[item]
        except KeyError:
            raise AttributeError("some customised error")

Which option is most Pythonic and elegant?

This question is related to python

The answer is


Your first example is perfectly fine. Even the official Python documentation recommends this style known as EAFP.

Personally, I prefer to avoid nesting when it's not necessary:

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        pass  # Fallback to dict
    try:
        return self.dict[item]
    except KeyError:
        raise AttributeError("The object doesn't have such attribute") from None

PS. has_key() has been deprecated for a long time in Python 2. Use item in self.dict instead.


try:
    #if it gone wrong then it will go to except
except:
    try:
        #if it also go wrong then it will go to except
    except:
        try:
            #if it also go wrong then  it will go to except
        except:
             print('write what is your need')

code for above content:

def():
    try:
        A = 5
        raise SyntaxError
    except:
        try:
           A = 5
           raise SyntaxError
       except:
           try:
               A = 5
               raise SyntaxError
           except:
               print('None')
   finally:
      return A
    

In my opinion, this would be the most Pythonic way to handle it, although and because it makes your question moot. Note that this defines __getattr__() instead of __getattribute__() , because doing so means it only has to deal with the "special" attributes being kept in the internal dictionary.

def __getattr__(self, name):
    """Only called when an attribute lookup in the usual places has failed"""
    try:
        return self.my_dict[name]
    except KeyError:
        raise AttributeError("some customized error message")

I like to avoid raising a new exception while handling an old one. It makes the error messages confusing to read.

For example, in my code, I originally wrote

try:
    return tuple.__getitem__(self, i)(key)
except IndexError:
    raise KeyError(key)

And I got this message.

>>> During handling of above exception, another exception occurred.

I wanted this:

try:
    return tuple.__getitem__(self, i)(key)
except IndexError:
    pass
raise KeyError(key)

It doesn't affect how exceptions are handled. In either block of code, a KeyError would have been caught. This is merely an issue of getting style points.


While in Java it's indeed a bad practice to use exceptions for flow control (mainly because exceptions force the JVM to gather resources (more here)), in Python you have two important principles: duck typing and EAFP. This basically means that you are encouraged to try using an object the way you think it would work, and handle when things are not like that.

In summary, the only problem would be your code getting too much indented. If you feel like it, try to simplify some of the nestings, like lqc suggested in the suggested answer above.


A good and simple example for nested try/except could be the following:

import numpy as np

def divide(x, y):
    try:
        out = x/y
    except:
        try:
            out = np.inf * x / abs(x)
        except:
            out = np.nan
    finally:
        return out

Now try various combinations and you will get the correct result:

divide(15, 3)
# 5.0

divide(15, 0)
# inf

divide(-15, 0)
# -inf

divide(0, 0)
# nan

(Of course, we have NumPy, so we don't need to create this function.)


I don't think it's a matter of being Pythonic or elegant. It's a matter of preventing exceptions as much as you can. Exceptions are meant to handle errors that might occur in code or events you have no control over.

In this case, you have full control when checking if an item is an attribute or in a dictionary, so avoid nested exceptions and stick with your second attempt.


Just be careful - in this case the first finally is touched, but skipped too.

def a(z):
    try:
        100/z
    except ZeroDivisionError:
        try:
            print('x')
        finally:
            return 42
    finally:
        return 1


In [1]: a(0)
x
Out[1]: 1

According to the documentation, it is better to handle multiple exceptions through tuples or like this:

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as e:
    print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error: ", sys.exc_info()[0]
    raise

If try-except-finally is nested inside a finally block, the result from "child" finally is preserved. I have not found an official explanation yet, but the following code snippet shows this behavior in Python 3.6.

def f2():
    try:
        a = 4
        raise SyntaxError
    except SyntaxError as se:
        print('log SE')
        raise se from None
    finally:
        try:
            raise ValueError
        except ValueError as ve:
            a = 5
            print('log VE')
            raise ve from None
        finally:
            return 6
        return a

In [1]: f2()
log SE
log VE
Out[2]: 6

For your specific example, you don't actually need to nest them. If the expression in the try block succeeds, the function will return, so any code after the whole try/except block will only be run if the first attempt fails. So you can just do:

def __getattribute__(self, item):
    try:
        return object.__getattribute__(item)
    except AttributeError:
        pass
    # execution only reaches here when try block raised AttributeError
    try:
        return self.dict[item]
    except KeyError:
        print "The object doesn't have such attribute"

Nesting them isn't bad, but I feel like leaving it flat makes the structure more clear: you're sequentially trying a series of things and returning the first one that works.

Incidentally, you might want to think about whether you really want to use __getattribute__ instead of __getattr__ here. Using __getattr__ will simplify things because you'll know that the normal attribute lookup process has already failed.


In Python it is easier to ask for forgiveness than permission. Don't sweat the nested exception handling.

(Besides, has* almost always uses exceptions under the cover anyway.)