Python Switch Over

Transitioning from 2 to 3


09 Feb 2019 View Comments
#computer #programming #python #python3

2018 has been an exciting year for me to develop my skills in Python. I had so much exposure, not entirely from work, but drove by my sole interest in Python (Python 3 especially). We use Python 2 mainly at work, but I honestly spend more time on Python 3 for my personal development at home. So I get to have experiences in both Python 2 and 3.

Python 2 and 3 are, in some ways similar, but there are still fair bits of differences between the two, which is why there are compatibility libraries available like six or future where it helps you port your Python 2 code to Python 3. However, I have not had a big enough project to use these libraries on my own. I heard good things about them though.

Whenever I needed to do the switch from Python 2 to 3, I used Python 3’s built-in tool called, 2to3. From my experiences, I have not yet come across a situation where it did not handle well (not that I tried a million times though). I suspect the may have a hard time converting some complicated and sophisticated lines of codes. I suggest reviewing the codes thoroughly after the conversion.

NOTE: When I am comparing between Python 2 and 3, I am comparing the somewhat latest versions of both.

What Changed?

There are a fair amount of little things that had been improved/deprecated from Python 2 to 3. Even though I love most of the changes made in Python 3, some features are still missing in Python. The changes are robust, durable and well-thought which is why I started to enjoy coding in Python 3.

1. Imports

There are a few subtle changes to the import itself. The main difference, I would say, is that we no longer require __init__.py to define our package. Yay!

Also, in Python 2, we would typically import like import xyz, but in Python 3, it is preferred to use from . import xyz syntax. We usually replace the dot with the package location (folder and filename). It is not mandated, but rather a good coding habit.

2. Print

Anyone who is somewhat familiar with Python would know this infamous change: print is treated as a function call in Python 3.

Instead of print "foobar" (in Python 2), we now call print as a function like this: print("foobar")

There is an option in Python 2 to enable using the print function like Python 3:

from __future__ import print_function
print("foobar")
import sys
print("barbaz", file=sys.stderr)

file=sys.stderr is the way to pipe the output to standard error. For the comparison, in Python 2, we had to do something like this to pipe to stderr: print >> sys.stderr, "barbaz"

3. Exceptions

There aren’t any significant changes to how we raise exceptions. If you are familiar with Python 2 syntax, the syntax for raising exceptions should be pretty much the same. However, there was some extra work done on the catching side.

We used to catch exceptions like this in Python 2:

try:
    raise RuntimeError()
except: RuntimeError, e:
    pass

Here is the Python 3 with subtle changes to how it is caught:

try:
    raise RuntimeError()
except: RuntimeError as e:
    pass

The comma was replaced with “as,” which is more concise and descriptive.

4. Division

There are a few changes to the integers in general. I want to focus on the division operator though. In Python 2, this is true:

5/2 # results 2
5.0/2 # results 2.5
5.0//2 # results 2

It is pretty similar in Python 3, but float is by default instead of rounding down to an integer (even when an integer is used). I like this update as I couldn’t understand better why python would round down automatically. There were numerous times, I got burned by the miscalculation of divisions in Python. As you can see from the example below, you can use // to mimic the Python 2 behaviour of round-down.

5/2 # results 2.5
5.0//2 # results 2

5. Strings/Unicodes

There have been a few radical revamp of Strings in Python 3. For the most critical part, Python 3 uses Unicode by default whereas Python 2 wasn’t.

Therefore, when porting, Python recommends prefixing the string with u'' on any existing Python 2 string like so, u'foobar'. This way it is supported in both Python 2 and Python 3 without any broken characters. As you may have noticed, the letter u refers to Unicode. You can optionally pass in below import in Python 2 to address Unicode issues.

from __future__ import unicode_literals 

This import takes care of having the u prefix on every string. If you are worried about backward compatibility, you can be explicit to the string like b'foobar' (used in Python 3) which would interpret the string as a “raw” byte string like Python 2.

You can contrarily think this way, unicode strings in Python 2 are equivalent to str in Python 3.

6. Classes

We were able to define classes like this which makes a distinct “class” type:

class Foo:
    pass

Then there is another way of defining a class:

class Foo(object):
    pass

We would have had to explicit inheritance from the “object.” Python 3 essentially inherit everything from the Object by default (like Java). Also, there were some changes in super calls, metaclasses, etc. I do not think it’s much helpful to show them here. You can search online easily for the changes if you are interested.

7. Dictionaries

Python 3 dictionaries enforce the Ordering of inserts now (above 3.6). The change can help in situations when you need to retrieve items from insertion order. The change is not equal to “sorted keys” like how “TreeMap” works in Java. I found it a bit annoying not having the treemap in Python Standard Library (but what can I do, I think you can even import extra libraries if you want)

Also, there were some syntax changes on how we iterate dictionaries.

In Python 2, we do something like:

for key in d.iterkeys():
    print key

for key, value in d.iteritems():
    print key, value

In Python 3, we no longer have the iter methods and have a distinct call on each (keys, values, items) like:

for key in d.keys():
    print(key)

for key, value in d.items():
    print(key, value)
Share this post

Me

I am a passionate programmer working in Vancouver. I strongly believe in art of algorithms and together with it to write clean and efficient software to build awesome products. If you would like to connect with me, choose one from below options :) You can also send me an email at