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.
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!
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!
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:
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 fixPlease go ahead and read the full documentation before you start converting your code.
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:
six
comes from the fact that two times three equals six.[future](https://pypi.org/project/future/)
package.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.
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
Just to whet your appetite a little more, here are a couple of advantages Python 3 has to offer.
Some of the advantages:
print
to be a statement. It’s more consistent if print
is a function.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.print
like this—[print(x) for x in range(10)]
—now because it is a function.print
function by assigning to builtins.print
, whereas you can’t do that with a statement.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.
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:
__eq__
is implemented for you.__repr__
is implemented as well.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')
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.
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.
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.
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.
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!
☞ Python Tutorials for Beginners - Learn Python Online
☞ Complete Python Tutorial for Beginners (2019)
☞ Learn Python in 12 Hours | Python Tutorial For Beginners
☞ Python Programming Tutorial | Full Python Course for Beginners 2019