= 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 [http://pythonhosted.org/six/ 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.