- IPython Interactive Computing and Visualization Cookbook
- Cyrille Rossant
- 1385字
- 2021-08-05 17:57:25
Choosing (or not) between Python 2 and Python 3
In this first recipe, we will briefly cover a transverse and kind of a prosaic subject: Python 2 or Python 3?
Python 3 has been available since 2008, but many Python users are still stuck with Python 2. By improving many aspects of Python 2, Python 3 has broken compatibility with the previous branch. Migrating to Python 3 may therefore require a significant investment.
Even if there aren't that many compatibility-breaking changes, a program that works perfectly fine in Python 2 may not work at all in Python 3. For example, your very first Hello World
Python 2 program doesn't work anymore in Python 3; print "Hello World!"
raises a SyntaxError
in Python 3. Indeed, print
is now a function rather than a statement. You should write print("Hello World!")
, which also works fine in Python 2.
Whether you start a new project or need to maintain an old Python library, the question of choosing between Python 2 and Python 3 arises. Here, we give some arguments and pointers that should let you make an informed decision.
Note
When we refer to Python 2, we especially mean Python 2.6 or Python 2.7, as these last versions of the Python 2.x branch are closer to Python 3 than Python 2.5 and earlier versions. It is more complicated to support Python 2.5+ and Python 3.x at the same time.
Similarly, when we refer to Python 3 or Python 3.x, we especially mean Python 3.3 or above.
How to do it...
First, what are the differences between Python 2 and Python 3?
Main differences in Python 3 compared to Python 2
Here is a partial list of differences:
- Instead of a statement,
print
is a function (parentheses are compulsory). - Division of integers yields floating-point numbers and not integers.
- Several built-in functions return iterators or views instead of lists. For example,
range
behaves in Python 3 likexrange
in Python 2, and the latter no longer exists in Python 3. - Dictionaries do not have the
iterkeys()
,iteritems()
, anditervalues()
methods anymore. You should use thekeys()
,items()
, andvalues()
functions instead. - The following is a quote from the official Python documentation:
"Everything you thought you knew about binary data and Unicode has changed."
- String formatting with
%
is deprecated; usestr.format
instead. - Instead of a statement,
exec
is a function.
Python 3 brings many other improvements and new features regarding syntax and standard library content. You will find more details in the references at the end of this recipe.
Now, you have basically two options for your project: stick with a single branch (Python 2 or Python 3), or maintain compatibility with both branches.
Python 2 or Python 3?
It is natural to have a preference for Python 3; it is the future, whereas Python 2 is the past. Why bother supporting a deprecated version of Python? Here are a few situations where you might want to keep compatibility with Python 2:
- You need to maintain a large project written in Python 2, and it would be too costly to update it to Python 3 (even if semiautomatic updating tools exist).
- Your project has dependencies that do not work with Python 3.
Note
Most libraries we will be using in this book support both Python 2 and Python 3. This book's code is also compatible with both branches.
- Your end users work on environments that do not support Python 3 well. For example, they may work in a large institution where deploying a new version of Python on many servers would be too costly.
In these situations, you may choose to stick with Python 2, with the risk that your code becomes obsolete in the near future. Otherwise, you could pick Python 3 and its shiny new features, with the risk of leaving behind Python 2 users. You could also write your code in Python 2 and make it ready for Python 3. Thus, you can reduce the number of changes that will be required during a subsequent port to Python 3.
Fortunately, you don't necessarily have to choose between Python 2 and Python 3. There are ways to support both versions at the same time. Even if this involves slightly more work than just sticking to a single branch, it can be quite interesting in certain cases. Note, however, that you may miss many Python 3-only features if you go down this road.
Supporting both Python 2 and Python 3
There are basically two ways to support both branches in your code: use the 2to3 tool, or write code that just works in both branches.
Using 2to3
2to3 is a program in the standard library that automatically converts Python 2 code to Python 3. For example, run 2to3 -w example.py
to migrate a single Python 2 module to Python 3. You can find more information on the 2to3 tool at https://docs.python.org/2/library/2to3.html.
You can configure your installation script so that 2to3 runs automatically when users install your package. Python 3 users will get the automatically-converted Python 3 version of your package.
This solution requires your program to be well-covered by a solid testing suite and a continuous integration system that tests both Python 2 and Python 3 (see the recipes about unit testing later in this chapter). This is how you can ensure that your code works fine in both versions.
Writing code that works in Python 2 and Python 3
You can also write code that works in Python 2 and Python 3. This solution is simpler if you start a new project from scratch. A widely-used method is to rely on a lightweight and mature module called six, developed by Benjamin Petersons. This module is only a single file, so you can easily distribute it with your package. Wherever you would use a function or feature that is only supported in one Python branch, you need to use a specific function implemented in six. This function either wraps or emulates the corresponding functionality, thus it can work in both branches. You can find more information on six at http://pythonhosted.org/six/.
This method requires you to change some habits. For example, to iterate over all items of a dictionary in Python 2, you would write the following code:
for k, v in d.iteritems(): # ...
Now, instead of the preceding code, you write the following code with six:
from six import iteritems for k, v in iteritems(d): # ...
The iteritems()
method of dictionaries in Python 2 is replaced by items()
in Python 3. The six module's iteritems
function internally calls one method or the other, depending on the Python version.
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
There's more...
As we have seen, there are many options you can choose regarding the Python 2 or Python 3 question. In brief, you should consider the following options:
- Decide very carefully whether you absolutely need to support Python 2 or not:
- If so, prepare your code for Python 3 by avoiding Python 2-only syntax or features. You can use six, 2to3, or similar tools.
- If not, stick to Python 3.
- In all cases, make sure your project has a solid testing suite, an excellent code coverage (approaching 100 percent), and a continuous integration system that tests your code against all versions of Python that you officially support
Here are several references on the subject:
- An excellent free book about porting code to Python 3, by Lennart Regebro, available at http://python3porting.com/
- Official recommendations on porting code to Python 3, available at https://docs.python.org/3/howto/pyporting.html
- Official wiki page about the Python 2/Python 3 question, available at https://wiki.python.org/moin/Python2orPython3
- Python 3 questions and answers, by Nick Coghlan, available at http://python-notes.curiousefficiency.org/en/latest/python3/questions_and_answers.html
- What's new in Python 3, available at https://docs.python.org/3.3/whatsnew/3.0.html
- Ten awesome features of Python that you can't use because you refuse to upgrade to Python 3, a presentation by Aaron Meurer, available at http://asmeurer.github.io/python3-presentation/slides.html
- Using the
__future__
module when writing the compatibility code, available at https://docs.python.org/2/library/__future__.html - Key differences between Python 2 and Python 3, available at https://sebastianraschka.com/Articles/2014_python_2_3_key_diff.html
See also
- The Writing high-quality Python code recipe
- The Writing unit tests with nose recipe