Skip to content

Python Compatibility

matteobachetti edited this page Feb 16, 2015 · 17 revisions

For PINT, we recommend following the writing portable code practices as specified by the Astropy project.

The target Python releases are:

  • Python 2: &ge 2.6

  • Python 3: &ge 3.3

This allows for easier writing of code that is portable between different Python versions.

The recommended workflow is to write Python 3 code that is compatible with Python 2, rather than vice versa.

Python 2/3 compatibility

A good start for Python 2/3 compatibility is adding the following line at the very top of each Python source:

#!python
from __future__ import (print_function, division, unicode_literals,
                        absolute_import)

This will allow to write Python 2 code with part of the new syntax introduced by Python 3, making the code automatically compatible with the two versions.

Division

While in Python 2 the division between two integers is always the integer part of the result (4/3 = 1), in Python 3 this has changed and now division correctly returns a float if required (4/3=1.33333...). Adding division to the __future__ imports makes division work this way also in Python 2. To execute an integer division, the operation is now a//b.

Print function

print is a function in Python 3. This means that while in Python 2 (without the print_function import from 'future') we wrote

#!python
print a

we now write

#!python
print(a)

print a, (a way not to print a newline at the end of the print) now becomes print(a, end='').

print >>fobj, a now becomes print(a, file=fobj)

Unicode

In Python 3, strings are by default Unicode while in Python 2 they were by default byte strings. By adding the from __future__ import unicode_literals, one instates the Python 3 behavior in all Python versions. To specify byte strings, now one has to add a letter b in front of the string b 'This is a byte string'

Import

Since Python 2.7, relative imports are allowed. PINT uses them, e.g. in models/spindown.py:

#!python
from .parameter import Parameter, MJDParameter
from .timing_model import TimingModel, MissingParameter

This is incompatible with Python 2.6. Adding the from __future__ import absolute_import line makes it work in Python &ge 2.5.