Migrating from Python 2 to Python 3
Modern Python has powerful features such as asynchronous programming (using async and await) and memory-efficient data processing with generators and iterators. These capabilities, found mainly in Python 3, can noticeably improve both performance and maintainability. Taking advantage of them often means migrating existing Python 2 projects, and the effort involved ranges from a simple conversion to a major refactor. To help you plan, here are some of the most important differences between the two versions.
This one is easy. Most of the time it’s just a matter of changing:
print "abcd"
to:
print("abcd")
This works in Python 2:
x = {1:2, 3:4, 5:6}
k = x.keys()
z = k[0:2]
# [1, 3]
In Python 3, keys() and items() return view objects that can’t be indexed or sliced, so k[0:2] raises an error. A quick (though not optimal) workaround is to wrap the result in list():
x = {1:2, 3:4, 5:6}
k = list(x.keys())
z = k[0:2]
# [1, 3]
In Python 2, xrange() is a lazy sequence generator, typically used in for loops, while range() builds a full list:
a = [i for i in xrange(23)]
# [0, 1, ... , 22]
b = range(23)
# [0, 1, ... , 22]
In Python 3, range() takes over the role of xrange(), and the old list-returning range() no longer exists. Where you need an actual list, a list comprehension (or list(range(...))) will do the job.
Exception handling in Python 2 looks cluttered:
try:
raise IOError, "file error";
except IOError, err:
print err
Python 3 is much cleaner:
try:
raise IOError("file error")
except IOError as err:
print(err)
These changes can break programs in surprising ways:
a = round(122.5)
b = 7/5
# Python 2:
# a = 123, b = 1
# Python 3:
# a = 122, b = 1.4
In short, Python 2 inspects the operand types and performs integer or floating-point division accordingly. Python 3 is more predictable: / always performs floating-point division.
Rounding is harder to reason about. Python 2 rounds halves away from zero, whereas Python 3 rounds halves to the nearest even number (banker’s rounding), which is why round(122.5) gives 122.
There are many more differences. For example, if your code uses urllib, every call site must be updated to the new module structure. On a more encouraging note, an automated tool can handle much of this tedious work: 2to3.