Python 2: end of life in January 2020

Is popularity the determining factor behind Python 2 end of life?

Not really. Python 3.0 was released in December 2008 and its main goal was to fix problems existing in Python 2. If so, why didn’t we switch to Python 3 earlier, you may ask. Well, the end of Python 2 support was initially planned for 2015. However, so many people were still using it back then, that the version’s end of life was postponed.

Nonetheless, since 2008 the number of Python 3 users has been growing much faster than the number of Python 2 supporters – which is clearly visible in google search, for example.

Python 2 vs Python 3 - popularity

Interest in Python 2 and 3 over time

Python 2 vs Python 3 - popularity by region

Interest in Python 2 and 3 – breakdown by region

If we take a closer look at the breakdown by region, it turns out that Python 3 is favored worldwide and beats its predecessor on average 65% to 35%. You can learn more about the popularity of both on Google Trends.

When to give up on Python 2 and migrate to Python 3


It’s clear that Python 3 is more popular these days. However, even though it’s been around for over a decade now, it didn’t prevent the number of Python 2 users from growing. If that’s the case, why should we stop using the older version now? The answer is pretty straightforward.

Since the 1st January 2020, Python 2 will no longer receive any support whatsoever from the core Python team. What’s more, many projects and tools have pledged to drop support for the older version of the programming language with the beginning of a new decade. Among them are some of the top libraries for machine learning like TensorFlow, NumPy, Matplotlib, as well as other projects such as Requests, sckit-learn, or Apache Spark to name a few. The full list of projects giving up on Python 2 is available here.

Projects sunsetting Python 2 support

What does it mean in practice? Basically, any bugs or security issues discovered in 2020 will not be handled which is a major inconvenience – if not a threat – for businesses still using Python 2. Without the full support of the said language version, such apps are in danger of becoming subject to hacker attacks, software stability issues, and security breaches.

This, of course, doesn’t mean that after January 1st your Python 2 code will suddenly stop working. If your Python application is stable you can maintain your v 2.7 environment and not worry about it too much. At the end of the day, migration to Python 3 is advisable if one or more of the following conditions apply:

  • You’re building a new project from scratch.
  • Your legacy project relies heavily on features that are different in Python 3. To name one example, Python 3 changes the way strings are handled, making Unicode strings default. This, in turn, provides better support for accented characters, foreign languages, etc. If your application depends on the robust handling of international characters, you should consider going for Python 3 only as it will be a lot harder to maintain code that works on both versions.
  • Your project relies on popular packages like scikit-learn that have announced plans to drop Python 2 support.
  • You’re concerned about the security vulnerability.


Python 2 vs Python 3: what has changed

Deciding to migrate your application from Python 2.x to Python 3.x, you need to remember that Python 3 is not backward-compatible. As mentioned before, it rectifies some fundamental design flaws and redundancies which results in simpler and more elegant code. This, however, also means that Python 2 code may not automatically compile under Python 3 environment. Of course, you may attempt to write the code compatible with both versions, e.g. using the six package that provides utility functions for smoothing over the differences between Python 2 and 3. However, in some cases, it may not be enough.

Bearing that in mind, let me quickly describe some of the major changes introduced in P3.

  • The print function

Although print syntax is probably the best-known change, I still believe it’s worth mentioning. In Python 3, the print statement has been replaced by the print() function.

Python 2.7.16
>>print "hello world"
hello world
Python 3.7.5
>>print("hello world")
hello world

  • Integer division

This one is a controversial change and a potentially hazardous one if you are porting code because it doesn’t raise SyntaxError and may go unnoticed. To avoid problems in this regard, remember about changing / to // for integer division when migrating from P2 to P3 – otherwise, you’ll end up with floats instead of integers.

Python 2.7.16
>>print 3 / 2
1
Python 3.7.5
>>print(3 / 2)
1.5

  • Unicode

Converting strings in P2 has been causing many issues: there are ASCII str() types, unicode(), and a no byte type. In P3, we finally have Unicode (utf-8) strings, and 2 byte classes: byte and bytearrays.

Python 2.7.16
>>print type(unicode('this is like a python3 str type'))
<type 'unicode'>
>>print type(b'byte type does not exist')
<type 'str'>
>>print 'they are really' + b' the same'
they are really the same
>>print type(bytearray(b'bytearray oddly does exist though'))
<type 'bytearray'>
Python 3.7.5
>>print('strings are now utf-8 \u03BCnico\u0394é!')
strings are now utf-8 μnicoΔé!
>>print('Python', python_version(), end="")
>>print(' has', type(b' bytes for storing data'))
>>print('and Python', python_version(), end="")
>>print(' also has', type(bytearray(b'bytearrays')))
and Python 3.4.1 also has <class 'bytearray'>
'note that we cannot add a string' + b'bytes for data'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-d3e8942ccf81> in <module>()
----> 1 'note that we cannot add a string' + b'bytes for data'
TypeError: Can't convert 'bytes' object to str implicitly

  • xrange

xrange() is quite popular in Python 2 for creating an iterable object, e.g. for loops or lists. Its behavior is similar to a generator due to lazy evaluation but you can iterate over it infinitely. Its “lazy-evaluation” gives xrange() the advantage of being faster than range(). In Python 3, xrange() has been renamed range(). Thus, a dedicated xrange() function no longer exists and its use in this language version will raise a NameError.

n = 10000
def test_range(n):
return for i in range(n):
pass

def test_xrange(n):
for i in xrange(n):
pass Python 2.7.16
>>print 'Python', python_version()
>>print '\ntiming range()'
%timeit test_range(n)
>>print '\n\ntiming xrange()'
%timeit test_xrange(n)
timing range()
1000 loops, best of 3: 433 µs per loop
timing xrange()
1000 loops, best of 3: 350 µs per loopPython 3.7.5
>>print('Python', python_version())
>>print('\ntiming range()')
%timeit test_range(n)
timing range()
1000 loops, best of 3: 520 µs per loop
>>print(xrange(10))
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-5-5d8f9b79ea70> in <module>()
----> 1 print(xrange(10))
NameError: name 'xrange' is not defined

  • Raising exceptions

Where Python 2 accepts both notations – the ‘old’ and the ‘new’ syntax – Python 3 raises a syntaxError if we don’t enclose the exception argument in parentheses.

Python 2.7.16
>>raise IOError, "file error"
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-8-25f049caebb0> in <module>()
----> 1 raise IOError, "file error"
IOError: file error
>>raise IOError("file error")
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-9-6f1c43f525b2> in <module>()
----> 1 raise IOError("file error")
IOError: file errorPython 3.7.5
>>raise IOError, "file error"
File "<ipython-input-10-25f049caebb0>", line 1
raise IOError, "file error"
^
SyntaxError: invalid syntax
The proper way to raise an exception in Python 3:
print('Python', python_version())
>>raise IOError("file error")
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-11-c350544d15da> in <module>()
1 print('Python', python_version())
----> 2 raise IOError("file error")
OSError: file error

  • Banker’s rounding

Compared to its predecessor, Python 3 has adopted a different way of rounding decimals. In the newer language version, decimals are rounded to the nearest even number.

Python 2.7.16
>>round(15.5)
16.0
>>round(16.5)
17.0
Python 3.7.5
>>round(15.5)
16
>>round(16.5)
16

  • Parsings users input

As compared to Python 2, raw_input() has been renamed to input() and the old input() no longer exists in the new version. In other words, Python 3 has fixed the input() function so that it always stores the user inputs as str objects.

Python 2.7.16
>>> my_input = input('enter a number: ')
enter a number: 123
>>> type(my_input)
<type 'int'>
>>> my_input = raw_input('enter a number: ')
enter a number: 123
>>> type(my_input)
<type 'str'>Python 3.7.5
>>> my_input = input('enter a number: ')
enter a number: 123
>>> type(my_input)
<class 'str'>

Migration from Python 2 to Python 3

If you’re hesitant about adjusting your work to Python 2 end of life, don’t worry – there are plenty of people who’ve already migrated their code to Python 3. The internet is filled with various resources describing how to handle certain problems during the transition. There are even converters like 2to3 or Python 2 to 3 which should help you go through the process smoothly. Naturally, Python has its own documentation about porting Python 2 code to Python 3 as well.  

So what should you do about Python 2 end of life?

To sum up, Python 2 is at its sunset as it won’t be supported from 1st January 2020 onwards. After that date, any bugs in the core code will not be handled anymore. It’s not like the Python code will stop working but if you feel this change may take its toll on your work, you should definitely migrate your code to Python 3. As P3 is not backward-compatible it will surely cost you some effort but in the end, you will gain a better and well-supported environment with many issues resolved and possibly many features yet to come.

Oython ebook Merixstudio

Further reading

  1. End of Life (EOL) for Python 2.7 is coming. Are you ready?
  2. Python 3 statement
  3. The key differences between Python 2.7.x and Python 3.x with examples
  4. Porting Python 2 Code to Python 3

Navigate the changing IT landscape

Some highlighted content that we want to draw attention to to link to our other resources. It usually contains a link .