Migrating from Python 2 to Python 3: A guide to preparing for the 2020 deadline

With just four months to go until support ends for Python 2, there are still some developers and projects that haven't made the switch to Python 3.

Python is eating the world: How one developer's side project became the hottest programming language Frustrated by programming language shortcomings, Guido van Rossum created Python. With the language now used by millions, Nick Heath talks to van Rossum about Python's past and explores what's next.

Python may be attracting new developers at a record rate, but a potential security issue is looming for developers who've failed to adopt the latest version of the programming language.

The introduction of Python 3 in 2008 modernized the decades-old language but also broke compatibility with earlier versions of Python.

With just four months to go until support ends for Python 2, there are still some developers and projects that haven't made the switch to Python 3.

The pressure to make the move is growing, with the Python 2 interpreter and bundled libraries due to cease receiving bug fixes from January 1st 2020.

The need to migrate will potentially affect many developers. Python's unstoppable rise is widely recognized -- largely fuelled by its use for machine learning -- with some predicting it will soon become the most popular programming language in the world.   

"Enterprises with applications running under any version of Python 2 need to migrate – and the sooner the better," said Bart Copeland, CEO at software development support company ActiveState.

"However, because migration to a new version of Python is a significant undertaking, it should not be rushed. Rather, migrating before the deadline will help developers take the time needed to do it well, and account for any unforeseen glitches well in advance."

SEE: Python is eating the world: How one developer's side project became the hottest programming language on the planet (cover story PDF) (TechRepublic)

One of the biggest potential issues is the number of Python 2 versions of popular software packages that are still being downloaded.

"Even if only a portion of these downloads are being used in live projects, the Python 2 EOL [End of Life] could potentially affect the security of millions of systems," writes the National Cyber Security Centre (NCSC) in an advisory.

Amid popular packages -- those downloaded millions of times each month -- just over 40% of downloads for scikit-learn were Python 2 versions, as were 37% for the TensorFlow package, and just over 30% for the Flask package.

ActiveState's Copeland says there are still significant deployments of Python 2 applications services and scripts.

"We've spoken to many organizations that are worried about the impending Python 2 EOL. Universally, they're concerned about inevitable code vulnerabilities and the impact they'll have on application security," he says.

Luckily being compatible with Python 3 doesn't mean replacing code wholesale, with it being possible to modify Python 2.6 code onwards to a form that is also compatible with a Python 3 interpreter.

"The recommended course of action is to modernize incrementally in order to address failures progressively," says Copeland.
Fintan Ryan, research director with the Application Platform Strategies team for analyst firm Gartner, says that aiming for cross-generational compatibility is a good way to prepare for migration.

"As an intermediate step it's definitely something that can be done and for a lot of organizations with a lot of code laying around it may be as far as they get," he says.

SEE: More must-read Python coverage (TechRepublic on Flipboard)

How to get ready to migrate

The Python Software Foundation already provides a comprehensive guide to how to achieve cross-generational compatibility for organizations that need to run both Python 2 and 3 side-by-side, and here's a summary of its advice.

  1. Drop support for Python 2.6 and older as it's far easier to migrate from Python 2.7, and if you have to run Python 2.6, look into using the six library for compatibility with Python 3.

  2. Make sure your setup.py file properly specifies which versions of Python your codebase supports, with the file including at least Programming Language :: Python :: 2 :: Only as a trove classifier.

  3. Your test suite should have at least 80% code coverage, the name given to how much of your source code is executed during testing. If you don't know your code coverage, use the tools provided by coverage.py.

  4. Learn the differences between Python 2 and Python 3 by reading Python's What's New doc and the free Porting to Python 3 book.

  5. Use Futurize or Modernize to make your Python 2 code Python 3-compatible, making sure to read the documentation so you can resolve the issues these can't handle.

  6. Be sure to accommodate changes to how integer division is handled between Python 2 and 3. For example, in Python 2 9 / 2 = 4 and in Python 3 9 / 2 = 4.5. If you've been using from __future__ import division in your code and the // operator for integer division then your code will already be Python 3 compatible.

  7. Python 3 makes changes to which data can be used with the str type, in order to make the distinction between text and binary data clearer. Unfortunately for code that deals with both text and binary data, you'll have to take the following steps to ensure your code is compliant. An optional static type checker, such as mypy, can also help determine whether you're misusing binary data in one version of Python compared to another.

  8. When running code that behaves differently based on which version of Python is running it is better to check whether a specific feature that is supported in Python 3 is able to run, rather than to check whether sys.version_info[0] is equal to 3.

  9. To help align any new code that is written with Python 3 and ensure its compatibility, use the following statements at the top of any new modules you create: from __future__ import absolute_import, from __future__ import division, and from __future__ import print_function.  The Pylint project and its --py3k flag will also stop incompatibilities from creeping into code.

  10. Check which software dependencies will block you from supporting Python 3 using the tools provided by the caniusepython3 project. 

  11. Once you've migrated code, update your classifiers in the setup.py file to contain Programming Language :: Python :: 3 to indicate your code supports Python 2 and 3.

  12. Make sure your code stays compatible with Python 2 and 3 by automating tests using tox and integrating this setup with your continuous integration system.

For migrating Python 2 to Python 3 code, the NCSC also recommends the 2to3 application, which attempts to automate the process.

Copeland adds that organizations focused on data science should also be planning on adopting Python 3, "as all of the data science package creators have announced their plans to migrate" by 2020, including those behind the popular packages NumPy, Requests, and TensorFlow.

There are also signs that after years of developers clinging on to Python 2.0, the majority of Python developers are now using Python 3, with JetBrains finding that 84% of programmers having made the switch.

Those who haven't migrated from Python 2 by the January 2020 deadline hits can also choose to pay for additional support from a third-party, with ActiveState offering support for both the Python 2 core language and standard libraries, as well as backported security fixes implemented in Python 3 core language code and third-party packages.

Alongside the security benefits of moving to Python 3, the NCSC has produced a list of useful features found in the latest version, including the yield from expression, unicode strings, a more capable print function, and complex with statements being easier to read.

If you want to keep on top of how long you've got left then you can check out this countdown clock.

Also see