[Python-Dev] Exception Reorg PEP checked in

James Y Knight foom at fuhm.net
Thu Aug 4 17:06:00 CEST 2005

>        +-- NamespaceError (rename of NameError)
>            +-- UnboundFreeError (new)
>            +-- UnboundGlobalError (new)
>            +-- UnboundLocalError

What are these new exceptions for? Under what circumstances are they  
raised? Why is this necessary or an improvement?

> Renamed Exceptions
> Renamed exceptions will directly subclass the new names. When the  
> old exceptions are instantiated (which occurs when an exception is  
> caught, either by a try statement or by propagating to the top of  
> the execution stack), a PendingDeprecationWarning will be raised.
> This should properly preserve backwards-compatibility as old usage  
> won't change and the new names can be used to also catch exceptions  
> using the old name. The warning of the deprecation is also kept  
> simple.

This will cause problems when a library raises the exception under  
the new name and an app tries to catch the old name. So the standard  
lib (or any other lib) cannot raise the new names. Because the stdlib  
must raise the old names, people will see the old names, continue  
catching the old names, and the new names will never catch on.

Perhaps it'd work out better to have the new names subclass the old  
names. Then you have to continue catching the old name as long as  
anyone is raising it, but at least you can raise the new name with  
impunity. I expect not much code actually raises ReferenceError or  
NameError besides that internal to python. Thus it would be  
relatively safe to change all code to catch the new names for those  
immediately. Lots of code raises RuntimeError, but I bet not very  
much code explicitly catches it.

Oh, but if the stdlib starts raising under the new names, that'll  
break any code that checks the exact type of the exception against  
the old name. Boo.

It'd be better to somehow raise a DeprecationWarning upon access, yet  
still result in the same object. Unfortunately I don't think there's  
any way to do that in python. This lack of ability to deprecate  
module attributes has bit me several times in other projects as well.  
Matt Goodall wrote the hack attached at the end in order to move some  
whole modules around in Nevow. Amazingly it actually seemed to  
work. :) Something like that won't work for __builtins__, of course,  
since that's accessed directly with PyDict_Get.

All in all I don't really see a real need for these renamings and I  
don't see a way to do them compatibly so I'm -1 to the whole idea of  
renaming exceptions.

> Removal of Bare except Clauses
> A SemanticsWarning will be raised for all bare except clauses.

Does this mean that bare except clauses change meaning to "except  
Exception" immediately? Or (I hope) did you mean that in Py2.5 they  
continue doing as they do now, but print a warning to tell you they  
will be changing in the future?


> import sys
> import types
> import warnings
> from twisted.python import reflect
> class ModuleWithDeprecations(types.ModuleType):
>     def __init__(self, original, deprecatedNames):
>         self.original = original
>         self.deprecatedNames = deprecatedNames
>     def __getattr__(self, name):
>         newName = self.deprecatedNames.get(name, None)
>         if newName is not None:
>             warnings.warn("nevow.%s is deprecated, please import %s  
> instead!"% (name,newName), DeprecationWarning, 2)
>             return reflect.namedAny(newName)
>         return getattr(self.original, name)
> # Evil hack? What evil hack!
> sys.modules['nevow'] = ModuleWithDeprecations(
>     sys.modules['nevow'],
>     {'formless': 'formless',
>      'freeform': 'formless.webform'
>      }
>     )

More information about the Python-Dev mailing list