Search code examples
pythonexceptiontry-catch

Difference between bare except and specifying a specific exception


I could write a simple except clause without writing an Exception in front of it. I mean, the last line could be like this :

except:
  print('Hit an exception other than KeyError or NameError!')

What is the point of writing Exception in front of an except clause?

try:
    discounted_price(instrument, discount)
except KeyError:
    print("There is a keyerror in your code")
except NameError:
    print('There is a TypeError in your code')
except Exception:
    print('an exception occured')

I tried writing an except clause without an Exception and it worked the same.

I know the point of catching specific errors. If I want to ask more clearly, what is the difference between these two clauses :

except Exception:
    print('an exception occured')

except :
    print('an exception occured')

Solution

  • A bare expect

    try:
        ...
    except:
        pass
    

    or catching any exception whatsoever

    try:
        ...
    except Exception:
        pass
    

    are bad practice, because you can be hiding bug or be interfering with the normal procedure of the program.

    You should only catch exception that you know how to handle, everything else you should let it propagate.

    For some example:

    Hide bug: it can hide some typo in your code as Caridorc example show making you think that you had a problem different than the real problem

    Interfering with the normal procedure: you can make it an unexpectedly unkillable program or get in the way of the normal procedure of the program by discarding an exception that another part of the code was expecting.

    like for example

    while True:
        try: 
            print("running")
        except:
            print("I'm immortal muahahaha")
    

    this piece of code now you can't stop with you usual control-z (control-z throw and KeyboardInterrupt exception into your program) so you now need to close the whole interpreter/kill it with the task admin just to stop it, and if this was unintended you just introduced a new bug and depending on what you're doing it can be catastrophic.

    To illustrate how catastrophic it can be, consider the following hypothetical case: imagine you make so benign function for a medical device and you put something like this

    try: 
        ...
    except:
        print("some error happens")
    

    now it just so happens that while you piece of code was running a HeartAttack exception was raised and your catch it all and ignore piece of code will do, well, just that, and here is the twist this device was a pacemaker... well, congratulation you just killed the poor guy.

    And that is why you should only catch the exception you know how to deal with, everything else you let it pass and hope that somebody along the line know how to deal with it, like in the example above, you and your piece of code don't know how to deal with a HeartAttack, but the pacemaker do and the pacemaker was the one that call your piece of code let it deal with it...


    for a no so extreme example consider this simple code

    def get_number_from_user():
        while True:
            try:
                return int(input("write a number: "))
            except:
                print("not a valid number try again")
    

    if your user was done with your program and this happens to be the thing running he/she might want to kill it with a control-z as you usually do with any program, but it will find that it doesn't work, the correct way here is to catch the error we know how to deal with in this case, namely ValueError, everything else isn't this function business

    def get_number_from_user():
        while True:
            try:
                return int(input("write a number: "))
            except ValueError:
                print("not a valid number try again")
    

    You also ask about the difference between

    try:
        ...
    except:
        pass
    

    and this

    try:
        ...
    except Exception:
        pass
    

    the difference is that a bare except can catch any and all kind of exception, that in python is anything that is or inherit from BaseException that sit at the top of the exception hierarchy, while except Exception will catch only Exception itself or anything that inherit from it (the same apply for any particular exception you put there), this small distinction allow to make some exceptions more special than other, like the aforementioned KeyboardInterrupt that inherit from BaseException instead of Exception, and that is used to signal that the user wants to terminate this program, so you should do so and this distinction is made basically so new programmers don't shoot themselves in the foot when using except Exception