Skip to content

Python Compatibility

Matteo Bachetti edited this page May 12, 2016 · 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: 2.6 or newer. This allows to make PINT function in "reasonably" old Linux machines

  • Python 3: 3.3 or newer.

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.

"Future"

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 make the new syntax introduced by Python 3 work also on Python 2, 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)

Strings and 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'

[... Add about the use of str(), the elimination of basestring, and so on]

Format specifications with the new mini-language are encouraged. Example:

print('Result: {0} # {1}'.format(result, comment))

From Python 2.7 on, the '0' and '1' above can be omitted (Result: {} # {} will produce the same output). Keep in mind, however, that this will not work in Python 2.6.

Import

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

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

This is incompatible out-of-the-box with Python 2.6, but adding the from __future__ import absolute_import line makes it work in Python 2.5 or newer.

Libraries

Pickle

pickle is called cPickle in Python 2 and pickle in Python 3. A workaround might be

#!python
try:
    # Python 2
    import cPickle as pickle
except:
    # Python 3
    import pickle