Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

People also ask

Is it a good practice to use try except else in Python?

The except block should only catch exceptions you are prepared to handle. If you handle an unexpected error, your code may do the wrong thing and hide bugs. An else clause will execute if there were no errors, and by not executing that code in the try block, you avoid catching an unexpected error.

Is it good practice to have nested try-catch?

Nesting try-catch blocks severely impacts the readability of source code because it makes it to difficult to understand which block will catch which exception.

Why is it best practice to have multiple except statements?

Why is it best practice to have multiple except statements with each type of error labeled correctly? Ensure the error is caught so the program will terminate In order to know what type of error was thrown and the.

Can you have nested try-catch in Python?

Whenever, you try to manipulate a file. The first try-catch block will try to catch any file opening exceptions. Only after that file is opened successfully, nested try-catch is executed and catch other errors. First step is to create a file named testFile.


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.


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.


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

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.


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.)


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")