DIPY supports Python versions from 2.6 to 3.5. In order to maintain code that supports both Python 2 and Python 3 versions, please follow these instructions.
There is useful advice here:
For any modules with print statements, and for any modules where you remember, please put:
from __future__ import division, print_function, absolute_import
As the first code line of the file, to use Python 3 behavior by default.
In Python 3,
__future__ import above,
and the function form:
In Python 2, integer division returns integers, while in Python 3
1. It’s very good to remember to put the
import above at the top of the file to make this default everywhere.
There are compatibility routines in
dipy.utils.six. You can often get
modules that have moved between the versions with (e.g.):
from dipy.utils.six.moves import configparser
six.py code and the six.py docs.
range returns an iterator in Python3, and
xrange is therefore redundant,
and it has been removed. Get
xrange for Python 2,
range for Python 3
from dipy.utils.six.moves import xrange
Or you might want to stick to
range for Python 2 and Python 3, especially
for small lists where the memory benefit for
xrange is small.
range returns an iterator for Python 3, you may need to wrap some
calls to range with
list(range(N)) to make the code compatible with Python 2
and Python 3.
Python 3 removed
reduce from the builtin namespace, this import works for
both Python 2 and Python 3:
from functools import reduce
The major difference between Python 2 and Python 3 is the string handling.
str) are always unicode, and so:
my_str = 'A string'
in Python 3 will result in a unicode string. You also need to be much more
explicit when opening files; If you want bytes, use:
open(fname, "rb"). If
you want unicode:
open(fname, "rt"). In the same way you need to be explicit if
import io; io.StringIO or
io.BytesIO for your file-like objects
containing strings or bytes.
basestring has been removed in Python 3. To test whether something is a
from dipy.utils.six import string_types isinstance(a_variable, string_types)
In versions of Python from 2.6 and on there is a function
next in the
builtin namespace, that returns the next result from an iterable thing. In
Python 3, meanwhile, the
.next() method on generators has gone, replaced by
.__next__(). So, prefer
obj.next() for generators, and
in general when getting the next thing from an iterable.
You can’t get away with
except ValueError, err now, because that raises a
syntax error for Python 3. Use
except ValueError as err instead.