# Exceptions in python # How do we catch exceptions? # Do they have to be inside a try block (indented)? # And code that is inside a try block # (even if the try block is in another function) # can be caught by its catching clauses print("---- handle exception with try-except block ----") try: denom = 0 print("attempt divide") print(10/denom) # raise an a ZeroDivisionError exception print("will never get here") # except: # use base/generic exception, catch any types of exception except ZeroDivisionError: # to be more specific on the type of exception print("Oops!!") print("finished catching exception!") # print("force crash: " + str(10/0)) # raise a ZeroDivisionError exception # not protected by the try-block # to protect the code, the code must be indented inside # the try block # try # is a keyword that declares the following block # of indented statements will be protected by # the subsequent catch block # except # is a keyword that declares the catch block # an exception not protected in some try block # will always crash the program ########################### # Multiple exceptions # What happens if there are multiple catches? # Nested try blocks and catches? # The first matching catch block is executed # and the exception is handled. # No other catch blocks are executed for that exception. # If no match, exception is propagated up the chain print("\n---- multiple exceptions ----") try: denom = 0 print("attempt divide") print(10/denom) print("will never get here") except Exception: # exception raised from print(10/denom) is catched here print("catches any exception!") except ZeroDivisionError: print("will never get here!") print("finished catching exception!") # we can have multiple except-blocks that go with # a single try-block # Exception is an object. It has a hierarchy # here are some exceptions and their sub-types # BaseException # -- KeyboardInterrupt # -- Exception # -- ArithmeticError # -- ZeroDivisionError # -- EnvironmentError # -- IOError (such as when dealing with files such as file not found) # -- EOFError # -- LookupError # -- IndexError # -- KeyError # -- NameError (such as use a variable before giving it a value) # -- SyntaxError # -- SystemError # -- TypeError (such as call a function with the wrong type) # -- ValueError ########################### # Exceptions as objects print("\n---- exception as an object ---- ") try: denom = 0 print("attempt divide") print(5/denom) print("will never get here") except Exception as e: # label an exception object with name e print("Problem: " + str(e)) # refer to e, print message that e holds, for debugging purpose print("finished catching exception!") ########################### # Raising an exception print("\n---- raise an exception ----") try: denom = 0 print("attempt divide") raise ZeroDivisionError("I raise an exception with custom message") # can specify our own message print("will never get here") except Exception as e: # Exception is a parent class of ZeroDivisionError exception print("Problem: " + str(e)) # print customized message print("finished catching exception!") # raise # is a keyword that we call in conjunction # with the exception's constructor ########################### # Clean up after exceptions print("\n---- clean up exceptions with finally ----") def openThisManyBuffers(number): try: # start opening buffers # ... something goes wrong raise IOError("couldn't open at some location in buffers") # at a particular location, IOError is raised # IOError is raised inside a try-block. # Computer tries to match corresponding except. except ZeroDivisionError: # not match IOError, thus not execute print("divided by zero") finally: # clean up, # execute before exception is propagated # to where the function was called print("always close all buffers") print("will not get here with IOError") openThisManyBuffers(50000) # open a lot of buffers (generally, we don't want to open these many) print("can't close buffers here") # finally # is a keyword that allows us to execute code # regardless if an exception was raised or not # in a try block # for example, leaving too many buffers open # will crash the program later