[Tutor] combining Python 2.x and Python 3

Paul McGuire ptmcg at austin.rr.com
Wed Mar 18 14:49:52 CET 2009


These are very interesting links, and I just downloaded the evoque code to
see how they handled the one "impossible" case that has stymied me in
supporting pyparsing under Python 2.x (pre-2.6) and Python 3.0 with a single
code base: exception handling.

For those new to this topic, here is the problem.  Python 2.x uses this
syntax (code in []'s is optional, syntax-wise):

try:
    ... body of try block ...
except exception_type[, exception_var]:
    ... body of except block ...

In Python 3.0, this has become:

try:
    ... body of try block ...
except exception_type[as exception_var]:
    ... body of except block ...


Searching through evoque's code, I found that nearly all excepts are of the
form:

except exception_type:

(3 are bare except:'s - eek!)

Unfortunately, pyparsing makes *heavy* use of exceptions for managing the
navigation through the parsing alternatives defined in the users parser
expression.  I have already removed all cases of "except exc_type, exc_var:"
where the exc_var is not used in the exception handling block, but there are
still some cases where I *must* have the actual exception that was raised.

I posted to Stephan Deibel's blog a comment asking how he resolved this -
here is his reply:
>>>
Instead of the version-specific except clause forms I use just 'except
SomeException:' or 'except:' and then use sys.exc_info() inside the except
block to get at the exception information. That returns a three-value tuple,
the second element of which is the same thing you would get for 'e' in
'except SomeException, e:' or 'except SomeException as e:'.
>>>

Well, this is certainly promising, but pyparsing already has performance
challenges, and adding another function call in an exception handler to work
around this syntax issue is not that attractive.  My rough timing shows that
calling exc_info to extract the exception variable incurs a ~30% performance
penalty over using "except exc_type, exc_var:".  Note that adding this code
would impact not only the Python 3.0 users, but would also degrade
performance for Python 2.x users using this code base.  I can certainly use
this trick in those parts of pyparsing that are not performance-critical
(when building the parser to begin with for instance, as opposed to the
actual parsing time).  But in the parse-time code, I'm unwilling to add 30%
to my users' parsing time.

-- Paul



More information about the Tutor mailing list