Python 2 to Python 3
Part of my work in different companies has been about the transition fromp python2 to python3. It used to be recommended to use 2to3
, but nowadays most of the efforts are around the use of __future__
as well as the future
and six
library
This is the most obvious point of conflict. The old print “string” doesn’t work anymore. Any program that uses print will suffer from this error immediately and not continue.
print "abc"
vs
print(abc)
New modules and classes names
A few of the libraries that come with python have changed their name to something else That affects to the oneliners too, like the http server.
- urllib
- StringIO
- mock
Low level is handled for you in py3
In python2 the choice between a high level python library and a low level c version of it is at import time.
Example:
import profile
import cProfile
In python3 the interpreter decides which version to use for you
String becomes unicode and bytes
In python2 there are two classes to handle string:
- str
- unicode
They can convert to each other with .decode(), .encode() or casting to unicode() and str(). Internally py2 uses str unless otherwise specified, and the handling of low level bytes and actual strings is mixed up. To make things worse, calling encode for a str creates another str.
In python3 these classes have been changed to:
- bytes
- str
default behavior
In python2, all strings are bytes by default, and only u''
strings are unicode. In order to change this, from __future__ import unicode_literals
converts all the literal strings to unicode. Because the default in py2 is to have the ascii byte representation This might break some stuff.
Workflow changes
most libraries use .decode()
and .encode()
to alter the meaning of a string. In python 3 strings are always encoded, and bytes are always decoded.
Absolute imports as default
from __future__ import absolute_import
makes python2 behave like python3.
Division
py2 division works like integer division when both parts are integers. Py3 returns a float. from __future__ import division
makes python2 behave like python3
Round
py2 division when rounding middle values (0.5) rounds to the further away from 0 value. round(0.5)
will return 1.0
. Python3 returns the banker division, returning the nearest to the even number. round(0.5)
returns 0
. It also fixes the odd behavior of returning float in all cases.
numpy and native ints and floats
Numpy int64
and other types no longer inherit from int. This means that any json serialization of these types will fail
Dictionary order has changed
The dictionary order is always the same in python2, as there is no hash randomization. For python <= 3.4 the order wasn’t guaranteed at all. from python 3.5 onwards the implementation changed and order was guaranteed to be the insertion order
Everything is views or defered
dictionary.items(), dictionary.values(), etc.. are now views, which means they don’t generate a copy of the content. Things like map, reduce, filter no longer return a list either.
The effect of this change is that things like dict.items()[0]
or json.dumps(map(...))
no longer works