[Python-Dev] Bare except clauses in PEP 348

Michael Chermside mcherm at mcherm.com
Thu Aug 25 14:28:44 CEST 2005


Raymond writes:
> Efforts to improve Py3.0 have spilled
> over into breaking Py2.x code with no compensating benefits. [...]
> We don't have to wreck 2.x in order to make 3.0 better.

I think you're overstating things a bit here.

> Remember, the ONLY benefit from the whole PEP is that in 3.0, it will no
> longer be necessary to write "except (KeyError, SystemExit):  raise".
> [...] IOW, there's nothing worth inflicting destruction on tons of
> 2.x code.

And now I *KNOW* you're overstating things. There are LOTS of benefits
to the PEP in 3.0. My own personal favorite is that users can be
guaranteed that all exceptions thrown will share a particular common
ancestor and type. And no one is proposing "destruction" of 2.x code.

On the other hand, I thought these were very good points:
> Bare
> except clauses appear in almost every Python book that has ever been
> written and occur at least once in most major Python applications.
         [...]
> I had thought the plan was to introduce Py3.0 capabilities into 2.x as
> they become possible but not to break anything.
         [...]
> I propose that the transition plan be as simple as introducing
> BaseException.  This allows people to write code that will work on both
> 2.x and 3.0.

I think the situation is both better than and worse than you describe. The
PEP is now proposing that bare "except:" be removed in Python 3.0. If I
understand Guido correctly, he is proposing that in 2.5 the use of
bare "except:" generate a PendingDeprecationWarning so that conscientious
developers who want to write code now that will continue to work in
Python 3.0 can avoid using bare "except:". Perhaps I'm misreading him
here, but I presume this was intended as a PENDINGDeprecationWarning so
that it's easy to ignore.

But it's a bit worse than it might seem, because conscientious users
aren't ABLE to write safe 2.5 code that will run in 3.0. The problem
arises when you need to write code that calls someone else's library
but then unconditionally recovers from errors in it. Correct 2.4 syntax
for this reads as follows:

    try:
        my_result = call_some_library(my_data)
    except (KeyboardInterrupt, MemoryError, SystemError):
        raise
    except:
        report_error()

Correct 3.0 syntax will read like this:

    try:
        my_result = call_some_library(my_data)
    except (KeyboardInterrupt, MemoryError, SystemError):
        raise
    except BaseException:
        report_error()

But no syntax will work in BOTH 2.5 and 3.0. The 2.4 syntax is
illegal in 3.0, and the 3.0 syntax fails to catch exceptions that
do not inherit from BaseException. Such exceptions are deprecated
(by documentation, if not by code) so our conscientious programmer
will never raise them and the standard library avoids doing so.
But "call_some_library()" was written by some less careful
developer, and may well contain these atavisims.

The only complete solution that comes to mind immediately is for
the raising of anything not extending BaseException to raise a
PendingDeprecationWarning as well. Then the conscientious developer
can feel confident again so long as her unit tests are reasonably
exhaustive. If we cannot produce a warning for these, then I'd
rather not produce the warning for the use of bare "except:".
After all, as it's been pointed out, if the use of bare "except:"
is all you are interested in it is quite easy to grep the code to
find all uses.

-- Michael Chermside



More information about the Python-Dev mailing list