Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to Except When You’re Excepting by Esther Nam

How to Except When You’re Excepting by Esther Nam

PyCon 2013

March 17, 2013
Tweet

More Decks by PyCon 2013

Other Decks in Programming

Transcript

  1. def  square_this(number):        """  Return  the  number  squared

     """        return  number  *  number  >>> square_this(3) 9
  2. def  square_this(number):        """  Return  the  number  squared

     """        return  number  *  number  >>> square_this(3) 9 >>> square_this(“number”) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in square_this TypeError: can't multiply sequence by non-int of type 'str'
  3. def  square_this(number):        return  number  *  number  

    >>> square_this(3) 9 >>> square_this(“number”) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in square_this TypeError: can't multiply sequence by non-int of type 'str'
  4. def  square_this(number):        return  number  *  number  

    >>> square_this(3) 9 >>> square_this(“number”) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in square_this TypeError: can't multiply sequence by non-int of type 'str'
  5. def  square_this(number):        return  number  *  number  

    >>> square_this(3) 9 >>> square_this(“number”) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in square_this TypeError: can't multiply sequence by non-int of type 'str'
  6. def  make_sandwich(self):        """  Make  a  sandwich  """

           sandwich.add_meat()        sandwich.add_cheese()        sandwich.add_pickle()        return  sandwich
  7. def  make_sandwich(self):        """  Make  a  sandwich  """

           sandwich.add_meat()        sandwich.add_cheese()        sandwich.add_pickle()        return  sandwich   def  add_meat(self):        """  Slice  meat  """        if  sandwich.meat  in  ['ham',  'beef']:                  raise  ValueError
  8. def  make_sandwich(self):        """  Make  a  sandwich  """

           sandwich.add_meat()        sandwich.add_cheese()        sandwich.add_pickle()        return  sandwich   def  add_meat(self):        """  Slice  meat  """        if  sandwich.meat  in  ['ham',  'beef']:                  raise  ValueError
  9. >>> sandwich = Sandwich("ham") >>> sandwich.make_sandwich() def  make_sandwich(self):    

       """  Make  a  sandwich  """        sandwich.add_meat()        sandwich.add_cheese()        sandwich.add_pickle()        return  sandwich   def  add_meat(self):        """  Slice  meat  """        if  sandwich.meat  in  ['ham',  'beef']:                  raise  ValueError
  10. >>> sandwich = Sandwich("ham") >>> sandwich.make_sandwich() Traceback (most recent call

    last): […] ValueError def  make_sandwich(self):        """  Make  a  sandwich  """        sandwich.add_meat()        sandwich.add_cheese()        sandwich.add_pickle()        return  sandwich   def  add_meat(self):        """  Slice  meat  """        if  sandwich.meat  in  ['ham',  'beef']:                  raise  ValueError
  11. def  make_sandwich(self):        """  Make  a  sandwich  """

           try:                sandwich.add_meat()        except  ValueError:                print  "Meat  is  murder!  Cheese  only"        sandwich.add_cheese()        sandwich.add_pickle()        return  sandwich  
  12. def  make_sandwich(self):        """  Make  a  sandwich  """

           try:                sandwich.add_meat()        except  ValueError:                print  "Meat  is  murder!  Cheese  only"        sandwich.add_cheese()        sandwich.add_pickle()        return  sandwich   def  add_meat(self):        """  Slice  meat  """        if  sandwich.meat  in  ['ham',  'beef']:                  sandwich.meat  =  None                raise  ValueError
  13. >>> sandwich.make_sandwich() def  make_sandwich(self):        """  Make  a

     sandwich  """        try:                sandwich.add_meat()        except  ValueError:                print  "Meat  is  murder!  Cheese  only"        sandwich.add_cheese()        sandwich.add_pickle()        return  sandwich   def  add_meat(self):        """  Slice  meat  """        if  sandwich.meat  in  ['ham',  'beef']:                  sandwich.meat  =  None                  raise  ValueError
  14. >>> sandwich.make_sandwich() Meat is murder! Cheese only >>> sandwich.meat >>>

    def  make_sandwich(self):        """  Make  a  sandwich  """        try:                sandwich.add_meat()        except  ValueError:                print  "Meat  is  murder!  Cheese  only"        sandwich.add_cheese()        sandwich.add_pickle()        return  sandwich   def  add_meat(self):        """  Slice  meat  """        if  sandwich.meat  in  ['ham',  'beef']:                  sandwich.meat  =  None                  raise  ValueError
  15. ERROR  =  -­‐1 def  a():        value  =

     b()                if  value  !=  ERROR:                do_the_next_thing()        else:                barf()  
  16. ERROR  =  -­‐1 def  a():        value  =

     b()                if  value  !=  ERROR:                do_the_next_thing()        else:                barf()   def  b():        bvalue  =  c()                if  bvalue  !=  ERROR:                return  bvalue  +  1        else:                barf()
  17. ERROR  =  -­‐1 def  a():        value  =

     b()                if  value  !=  ERROR:                do_the_next_thing()        else:                barf()   def  b():        bvalue  =  c()                if  bvalue  !=  ERROR:                return  bvalue  +  1        else:                barf() def  c():        return  ERROR
  18. def  a():        try:        

             value  =  b()                do_the_next_thing()        except  ValueError:                barf()   def  b():        bvalue  =  c()              return  bvalue  +  1 def  c():        something_that_causes_ValueError()        #  Oh  no,  a  ValueError  was  raised!        return  cvalue
  19. enum  {        CMDERR_OPTION_UNKNOWN  =  -­‐3,  /*  unknown

     -­‐option  */        CMDERR_OPTION_AMBIGUOUS  =  -­‐2,  /*  ambiguous  -­‐option  */        CMDERR_OPTION_ARG_MISSING  =  -­‐1,  /*  argument  missing  for  -­‐option  */        CMDERR_UNKNOWN,  /*  unknown  command  */        CMDERR_AMBIGUOUS,  /*  ambiguous  command  */        CMDERR_ERRNO,  /*  get  the  error  from  errno  */        CMDERR_NOT_ENOUGH_PARAMS,  /*  not  enough  parameters  given  */        CMDERR_NOT_CONNECTED,  /*  not  connected  to  server  */        CMDERR_NOT_JOINED,  /*  not  joined  to  any  channels  in  this  window  */        CMDERR_CHAN_NOT_FOUND,  /*  channel  not  found  */        CMDERR_CHAN_NOT_SYNCED,  /*  channel  not  fully  synchronized  yet  */        CMDERR_ILLEGAL_PROTO,  /*  requires  different  chat  protocol  than  the  active  server  */        CMDERR_NOT_GOOD_IDEA,  /*  not  good  idea  to  do,  -­‐yes  overrides  this  */        CMDERR_INVALID_TIME,  /*  invalid  time  specification  */        CMDERR_INVALID_CHARSET,  /*  invalid  charset  specification  */        CMDERR_EVAL_MAX_RECURSE,  /*  eval  hit  recursion  limit  */        CMDERR_PROGRAM_NOT_FOUND  /*  program  not  found  */ };
  20. +-- Exception +-- StopIteration +-- StandardError | +-- BufferError |

    +-- ArithmeticError | | +-- FloatingPointError | | +-- OverflowError | | +-- ZeroDivisionError | +-- AssertionError | +-- AttributeError | +-- EnvironmentError | | +-- IOError | | +-- OSError | | +-- WindowsError (Windows) | | +-- VMSError (VMS) | +-- EOFError | +-- ImportError | +-- LookupError | | +-- IndexError | | +-- KeyError | +-- MemoryError | +-- NameError | | +-- UnboundLocalError | +-- ReferenceError | +-- RuntimeError | | +-- NotImplementedError | +-- SyntaxError | | +-- IndentationError | | +-- TabError | +-- SystemError | +-- TypeError | +-- ValueError | +-- UnicodeError | +-- UnicodeDecodeError | +-- UnicodeEncodeError | +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning +-- SyntaxWarning +-- UserWarning +-- FutureWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning http://docs.python.org/2/library/exceptions.html#exception-hierarchy
  21. Catch all the exceptions? try:        results  =

     run_query() except:        handle_error()  
  22. Catch all the exceptions? try:        results  =

     run_query() except:        handle_error()
  23. Catch all the exceptions? try:        results  =

     run_query() except  Exception:        handle_error()  
  24. try:        results  =  run_query() except  Exception:  

         return_empty_rows()   def  run_query():        connect_to_db()        sort_rows()         def  connect_to_db():        if  connection_is_dead:                raise  DatabaseNotConnectedError
  25. try:        results  =  run_query() except  Exception:  

         handle_error() def  run_query():        connect_to_db()        sort_rows()         def  connect_to_db():        if  connection_is_dead:                raise  DatabaseNotConnectedError
  26. try:        results  =  run_query() except  Exception:  

         handle_error() def  run_query():        connect_to_db()        sort_rows()         def  connect_to_db():        if  connection_is_dead:                raise  DatabaseNotConnectedError
  27. try: do_some_math() # ZeroDivisionError is a subclass of # ArithmeticError

    except ZeroDivisionError: just_die() except ArithmeticError: try_to_handle_this() Catching granular exceptions
  28. Catching lots of exceptions? try: do_some_math() except OneException: just_die() except

    AnotherException: try_to_handle_this() except YetAnotherException: just_log_this_one() except YetAnotherException: i_dunno_what_to_do_anymore()
  29. try: do_some_math() except OneException: just_die() except AnotherException: try_to_handle_this() except YetAnotherException:

    just_log_this_one() except YetAnotherException: i_dunno_what_to_do_anymore() Catching lots of exceptions? Re-think your inputs
  30. Re-try for attempt in number_of_attempts: connected = False try: connect_to_server()

    connected = True except ConnectionFail: wait_one_second() return connected
  31. +-- Exception +-- StopIteration +-- StandardError | +-- BufferError |

    +-- ArithmeticError | | +-- FloatingPointError | | +-- OverflowError | | +-- ZeroDivisionError | +-- AssertionError | +-- AttributeError | +-- EnvironmentError | | +-- IOError | | +-- OSError | | +-- WindowsError (Windows) | | +-- VMSError (VMS) | +-- EOFError | +-- ImportError | +-- LookupError | | +-- IndexError | | +-- KeyError | +-- MemoryError | +-- NameError | | +-- UnboundLocalError | +-- ReferenceError | +-- RuntimeError | | +-- NotImplementedError | +-- SyntaxError | | +-- IndentationError | | +-- TabError | +-- SystemError | +-- TypeError | +-- ValueError | +-- UnicodeError | +-- UnicodeDecodeError | +-- UnicodeEncodeError | +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning +-- SyntaxWarning +-- UserWarning +-- FutureWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning http://docs.python.org/2/library/exceptions.html#exception-hierarchy
  32. +-- Exception +-- StopIteration +-- StandardError | +-- BufferError |

    +-- ArithmeticError | | +-- FloatingPointError | | +-- OverflowError | | +-- ZeroDivisionError | +-- AssertionError | +-- AttributeError | +-- EnvironmentError | | +-- IOError | | +-- OSError | | +-- WindowsError (Windows) | | +-- VMSError (VMS) | +-- EOFError | +-- ImportError | +-- LookupError | | +-- IndexError | | +-- KeyError | +-- MemoryError | +-- NameError | | +-- UnboundLocalError | +-- ReferenceError | +-- RuntimeError | | +-- NotImplementedError | +-- SyntaxError | | +-- IndentationError | | +-- TabError | +-- SystemError | +-- TypeError | +-- ValueError | +-- UnicodeError | +-- UnicodeDecodeError | +-- UnicodeEncodeError | +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning +-- SyntaxWarning +-- UserWarning +-- FutureWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning http://docs.python.org/2/library/exceptions.html#exception-hierarchy
  33. +-- Exception +-- StopIteration +-- StandardError | +-- BufferError |

    +-- ArithmeticError | | +-- FloatingPointError | | +-- OverflowError | | +-- ZeroDivisionError | +-- AssertionError | +-- AttributeError | +-- EnvironmentError | | +-- IOError | | +-- OSError | | +-- WindowsError (Windows) | | +-- VMSError (VMS) | +-- EOFError | +-- ImportError | +-- LookupError | | +-- IndexError | | +-- KeyError | +-- MemoryError | +-- NameError | | +-- UnboundLocalError | +-- ReferenceError | +-- RuntimeError | | +-- NotImplementedError | +-- SyntaxError | | +-- IndentationError | | +-- TabError | +-- SystemError | +-- TypeError | +-- ValueError | +-- UnicodeError | +-- UnicodeDecodeError | +-- UnicodeEncodeError | +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning +-- SyntaxWarning +-- UserWarning +-- FutureWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning http://docs.python.org/2/library/exceptions.html#exception-hierarchy | +-- RuntimeError | | +-- NotImplementedError | +-- SyntaxError | | +-- IndentationError | | +-- TabError | +-- SystemError | +-- TypeError | +-- ValueError | +-- UnicodeError | +-- UnicodeDecodeError | +-- UnicodeEncodeError | +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning
  34. exception ValueError •Raised when a built-in operation or function receives

    an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception such as IndexError.
  35. from Bakeries import NewYorkBakery from Bakeries import NewYorkBakeryException def make_sandwich(self):

    try: sandwich.get_bread() sandwich.get_meat() except MeatException: return_cheese_sandwich() except SandwichException: return_failed_sandwich() def get_bread(self): try: bread = NewYorkBakery() except NewYorkBakeryException: raise SandwichException
  36. from Bakeries import CaliforniaBakery from Bakeries import CaliforniaBakeryException def make_sandwich(self):

    try: sandwich.get_bread() sandwich.get_meat() except MeatException: return_cheese_sandwich() except SandwichException: return_failed_sandwich() def get_bread(self): try: bread = CaliforniaBakery() except CaliforniaBakeryException: raise SandwichException
  37. try: file = open(‘file.txt’, ‘r’) except IOError as error: print

    “Can’t open file, screw it” else: # We can do this only if the exception # was not raised. If read() raises an # IOError, we can handle it differently contents = file.read() else
  38. finally try: file = open(‘file.txt’, ‘r’) except IOError as error:

    print “Can’t open file, screw it” finally: file.close()
  39. from contextlib import contextmanager @contextmanager def try_this(): try: yield #

    calls functions in try_this() except (ValueError, TypeError): handle_that_exception() finally: clean_up_step() def my_function(): with try_this(): # this is the context do_something() do_something_else()
  40. Every bug is 2 bugs 1. the bug in the

    code 2. the test you didn’t write
  41. NewCars Tech Team SoCal Python Audrey Roy Danny Greenfeld Chris

    McDonough Doug Napoleone Rachel Sanders Thanks
  42. References http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/ http://codemonkeyism.com/7-good-rules-to-log-exceptions/ http://docs.python.org/2/tutorial/errors.html http://docs.python.org/3.0/whatsnew/3.0.html http://doughellmann.com/2008/05/pymotw-contextlib.html http://en.wikipedia.org/wiki/Defensive_programming http://en.wikipedia.org/wiki/Exception_safety http://jeffknupp.com/blog/2013/02/06/write-cleaner-python-use-exceptions/ http://jessenoller.com/blog/2009/02/03/get-with-the-program-as-contextmanager-completely-

    different http://politechnosis.kataire.com/2008/02/all-exceptions-are-handled.html http://stackoverflow.com/questions/696047/re-raising-exceptions-with-a-different-type-and- message-preserving-existing-inf http://stackoverflow.com/questions/7108193/frequently-repeated-try-except-in-python?rq=1 http://stackoverflow.com/questions/77127/when-to-throw-an-exception http://today.java.net/article/2006/04/04/exception-handling-antipatterns http://www.blog.pythonlibrary.org/2012/08/02/python-101-an-intro-to-logging/ http://www.itmaybeahack.com/homepage/books/nonprog/html/p09_exc_iter/ p09_c01_exception.html#designing-exceptionshttps://en.wikipedia.org/wiki/ There_are_known_knowns#Quoted_from_Persian_literature