Why You Must Migrate to Python 3 Now

Why You Must Migrate to Python 3 Now

  • 480

I could keep raving about Python 3 vs. Python 2, but by now you should be convinced. The simple fact that support for Python 2 will be dropped somewhere after April 2020 should be enough for you to start converting those codebases!

It’s No Longer Supported

Support for Python 2 should have stopped at the beginning of 2020. However, it has become clear that the last major 2.7.x release will be in April 2020. After that, all development will cease for Python 2. This means there will be no security updates.

Many package maintainers have migrated to Python 3. Some still support Python 2, while others already dropped support. After April 2020, most packages will gradually stop supporting it.

Python 3.0 was released on December 3, 2008. So yeah, we’ve all had plenty of time to migrate. If you still haven’t, you should make it a top priority right now. At the max, you should be running Python 3 before the end of 2020. Otherwise, you will be at risk of vulnerabilities, non-functioning software, etc.

How to Check Which Version You’re Running

Just in case you don’t know or never cared, you can check your current Python version with the following command:

$ python --version
Python 2.7.16

This works on any OS, including Windows. Hopefully, yours says something like 3.7.x or even higher. But if it says 2.7.x, don’t worry just yet.

On many systems, both versions of Python are installed. Usually, Python 2 runs when you enter python and Python 3 when you enter python3.

Try it:

python3 --version
Python 3.7.6

If your output looks similar, congratulations. You already have Python 3 installed!

How to Upgrade/Install

I discovered this terrific site. It tells you exactly how to install Python 3 on Windows, Linux, macOS, and even Chromebooks. Go check it out and follow the guide there. I can’t do a better job!

How to Migrate Your Code

Now that you have Python 3 running, it’s time to upgrade your code. It’s not hard to upgrade your code. and you can follow multiple strategies. Most libraries are Python 3-compatible by now.

So all you need to do is:

  1. upgrade your own code
  2. if needed, upgrade to newer versions of dependencies that are Python 3 compatible

2to3

2to3 is a Python program that reads Python 2 source code and applies a series of fixers to transform it into valid Python 3 code. The standard library contains a rich set of fixers that will handle almost all code.

A notable change in Python 3 is that print is now a function called print(). For example, this Python 2 code:

def greet(name):
    print "Hello, {0}!".format(name)
print "What's your name?"
name = raw_input()
greet(name)

Can be converted by calling:

$ 2to3 greet.py

By default, this only prints the difference to your screen. But after inspection, you can use the -w option and it actually changes the file:

$ 2to3 -w greet.py

The original file is changed and the old file will be saved as greet.py.bak. The result:

def greet(name):
     print("Hello, {0}!".format(name))
 print("What's your name?")
 name = input()
 greet(name)

Some of the more interesting flags for 2to3 are:

  • -l — list all fixers
  • -x — excludes selected fixer
  • -f — explicitly run only this fix

Please go ahead and read the full documentation before you start converting your code.

Six

six is a Python 2 and 3 compatibility library. The project helps codebases to support both Python 2 and 3. I would recommend migrating completely to Python 3 with 2to3, but if you can’t — for whatever reason — you can at least make your codebase work on both versions.

Six offers functions that smooth the differences in syntax between Python 2 and 3. An easy-to-grasp example of this is six.print_(). In Python 3, printing is done with the print() function. In Python 2, print works without the parentheses. So by using six.print_(), you can support both languages with one statement.

Facts:

  • The name six comes from the fact that two times three equals six.
  • For a similar library, also check out the [future](https://pypi.org/project/future/) package.

Upgrade your packages

You may need to upgrade the packages you depend on. For each package, try to find out if it already supports Python 3. If it doesn’t, find a version that does. You may have to alter some code since APIs tend to change over time.

Check for a minimum-required Python version

After you migrate your code, you can check for the Python version in your code. This way, you can ensure you and your users are not running your script with an incompatible version, which will cause incomprehensible errors and frustration. Use a simple check like this:

if not sys.version_info > (2, 7):
   # berate your user for running a 10 year
   # python version
elif not sys.version_info >= (3, 5):
   # Kindly tell your user (s)he needs to upgrade
   # because you're using 3.5 features

check_python_version.py

Some Advantages of Python 3

Just to whet your appetite a little more, here are a couple of advantages Python 3 has to offer.

Print is no longer a statement but a built-in function

Some of the advantages:

  • There’s really no reason for print to be a statement. It’s more consistent if print is a function.
  • Since print is a function, it can be passed as an argument to functions that expect a function. Take for example a function that requires another function to further process your data as an argument. For simple mocking/debugging, you can now also pass the print() function.
  • You can use print like this—[print(x) for x in range(10)]—now because it is a function.
  • You can override the print function by assigning to builtins.print, whereas you can’t do that with a statement.

Unicode

In Python 3, every string is by default a Unicode string. In Python 2, a string defaults to an ASCII string, limiting the range of characters it can handle. If you wanted a Unicode string, you had to explicitly create one like this:

# no longer needed in Python 3
unicode_sting = u'Ümlaut? Nō prōblem!'

This is a must-have for many countries.

Data classes

Since version 3.7, which is fairly recent, Python offers data classes. There are several advantages over regular classes or other alternatives, like returning multiple values or dictionaries:

  • A data class requires a minimal amount of code.
  • You can compare data classes because __eq__ is implemented for you.
  • You can easily print a data class for debugging because __repr__ is implemented as well.
  • Data classes require type hints, reducing the chances of bugs.

Here’s an example of a data class at work:

from dataclasses import dataclass

@dataclass
class Card:
    rank: str
    suit: str
    
card = Card("Q", "hearts")

print(card == card)
# True

print(card.rank)
# 'Q'

print(card)
Card(rank='Q', suit='hearts')

dataclass.py

Merging dictionaries (Python 3.5+)

Since Python 3.5, it became easier to merge dictionaries:

dict1 = { 'a': 1, 'b': 2 }
dict2 = { 'b': 3, 'c': 4 }
merged = { **dict1, **dict2 }
print (merged)
# {'a': 1, 'b': 3, 'c': 4}

merging_dicts.py

If there are overlapping keys, the keys from the first dictionary will be overwritten.

Divisions became more predictable

In Python 2, the division operator ( / ) defaults to an integer division unless one of the operands is a floating-point number. So you have this behavior:

# Python 2
5 / 2 = 2
5 / 2.0 = 2.5

In Python 3, the division operator defaults to a floating-point division and the // operator became an integer division. So we get:

Python 3
5 / 2 = 2.5
5 // 2 = 2

For the complete motivation behind this change, you should read PEP-0238.

Meaningful comparisons

In Python 2, you could compare anything to everything. The following example would all return True:

print "a string" > 2
print None < 5

It makes no sense and can hide bugs.

In Python 3, these comparisons will throw a TypeError exception.

No more range vs. xrange

Python 2 had two range functions: range and xrange. The latter was faster since it was based on iterators. In Python 3, range has become xrange and the xrange name was dropped. It’s one of the examples where Python became less confusing for learners.

Wrap-Up

I could keep raving about Python 3 vs. Python 2, but by now you should be convinced. The simple fact that support for Python 2 will be dropped somewhere after April 2020 should be enough for you to start converting those codebases!

Thank you for reading. If you find errors or inconsistencies, please leave a private note or a comment so I can fix them. If you have anything useful to add, please don’t refrain! You’ll be helping lots of people!