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, print
is a function. Please use the __future__
import above,
and the function form:print(something)
, whenever print
is used.
In Python 2, integer division returns integers, while in Python 3 3/2
returns 1.5
not 1
. It’s very good to remember to put the __future__
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
See the 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
with:
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.
Because 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.
Strings (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
you want 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
string, use:
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 next(obj)
to obj.next()
for generators, and
in general when getting the next thing from an iterable.