Making an application compatible with Python 2.5 to 3.2 at the same time

Due to the wide range of Python versions on platforms supported by modRana, the modRana Python source code needs to work on Python 2.5(Maemo 5), Python 3.2(BlackBerry 10) and all versions in between(other platforms).

The six compatibility library

The six compatibility library aims to make writing code that is both Python 2 and 3 compatible easy by abstracting the main differences.

Exception handling

The main difficulty in writing code that is both Python 2 and 3 compatible is getting to the exception object.

The old syntax that works in all recent Python 2 (at least 2.5-2.7) versions looks like this:

except Exception, e:

The variable e contains the exception that occurred. This syntax is not supported by Python 3.

An alternative syntax is supported in Python 2.6, 2.7 and all Python 3 versions:

except Exception as e:

Again, e contains the exception object.

As long as Python 2.5 needs to be supported, this is a problem, as Python 2.5 does not support the new as notation and Python 3 on the other hand does not support the old comma notation.

Fortunately, there is a workaround:

except Exception:
    e = sys.exc_info()[1]

or alternatively for easy find & replace a standalone version independent on external imports:

except Exception:
    import sys
    e = sys.exc_info()[1]

This piece of code might look weird, but works in Python 2.5 - 3.3+

If Python 2.5 doesn't have to be supported, just using the as syntax is enough for the exception handling code to be Python 2.6-3.3+ compatible.

Text vs binary data

Python 3 tries to enforce quite strong type checking for text vs binary data. There for all open calls need to properly use the b flag with working with binary data. Python 2 also understands this flag, so keeping file opening compatible is easy.

Unicode handling

The u prefix used for marking up Unicode data in Python 2 is gone in Python 3.0-3.2, but was reintroduced in Python 3.3. The six compatibility library has the u() function, that can be used the replace the u prefix and abstract it's behavior in Python 2 & 3.

Standard library renaming

Some modules in in the Python standard library very renamed, moved and even split for Python 3.

The six library provides aliases for most moved and renamed modules, but does not cover modules that were split, such as the urllib module. Fortunately urrllib was only split while keeping the functions API-compatible. So a possible workaround is to only import the functions, such as urlopen, not the whole module from the correct module, based on current Python version.

The print() function

In Python 3, print is no longer a statement but a function. Using:

print "Hello world"

Will result in syntax error exception.

The correct way in Python 3 is:

print("Hello world")

Fortunately, the print function can be used as far back as Python 2.5, so no version specific code is needed for this. All prints just need to be converted to using the print function. This can be easily done automatically using regular expressions or semi-automatically with the ubiquitous search and replace functionality available in most editors.

Last modified 6 years ago Last modified on Jun 12, 2013 11:18:23 PM