[Python-Dev] Re: __except__ use cases

Nick Coghlan ncoghlan at gmail.com
Sun Apr 24 04:40:04 CEST 2005

holger krekel wrote:
> On a side note, I don't see too much point in having __except__ 
> return something when it is otherwise easy to say: 
>     def __except__(self, typ, val, tb): 
>         self.abort_transaction() 
>         raise typ, val, tb 

It has to do with "Errors should never pass silently, unless explicitly 
silenced". Consider:

      def __except__(self, typ, val, tb):

With __except__ returning a value, the implicit 'return None' means that the 
exception is propagated by default. Without the 'suppress exception' boolean 
return value, this naive handler would not only abort the transaction, but 
swallow each and every exception that occured inside the 'with' block.

Another common error with a manual reraise would involve not including the 
traceback properly, leading to difficulties with debugging.

IOW, returning a value from __except__ should make the exception handlers 
cleaner, and easier to 'do right' (since reraising simply means returning a 
value that evaluates to False, or falling off the end of the function). 
Suppressing the exception would require actively adding 'return True' to the end 
of the handler.

> But actually i'd like to to mention some other than
> transaction-use cases for __except__, for example with
>     class MyObject: 
>         def __except__(self, typ, val, tb): 
>             if isinstance(val, KeyboardInterrupt): 
>                 raise 
>             # process exception and swallow it

s/raise/return True/ for the return value version.

>     def __getattr__(self, name): 
>         Key2AttributeError: 
>             return self._cache[key]
>         ... 
> with an obvious __except__() implementation for
> Key2AttributeError.

Seeing this example has convinced me of something. PEP 310 should use the 'with' 
keyword, and 'expression block' syntax should be used to denote the 'default 
object' semantics proposed for Python 3K. For example:

class Key2AttributeError(object):
     def __init__(self, obj, attr):
             .obj_type = type(obj)
             .attr = attr
     def __except__(self, ex_type, ex_val, ex_tb):
         if isinstance(ex_type, KeyError):
                  raise AttributeError("%s instance has no attribute %s"
                                        % (.obj_type, .attr))

# Somewhere else. . .
     def __getattr__(self, name):
         with Key2AttributeError(self, key):
                 return ._cache[key]


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-Dev mailing list