@@ -17,7 +17,8 @@ Porting Python 2 Code to Python 3
1717 please see :ref: `cporting-howto `.
1818
1919 If you would like to read one core Python developer's take on why Python 3
20- came into existence, you can read Nick Coghlan's `Python 3 Q & A `_.
20+ came into existence, you can read Nick Coghlan's `Python 3 Q & A `_ or
21+ Brett Cannon's `Why Python 3 exists `_.
2122
2223 For help with porting, you can email the python-porting _ mailing list with
2324 questions.
3233#. Make sure you have good test coverage (coverage.py _ can help;
3334 ``pip install coverage ``)
3435#. Learn the differences between Python 2 & 3
35- #. Use Modernize _ or Futurize _ to update your code (``pip install modernize `` or
36- ``pip install future ``, respectively)
36+ #. Use Futurize _ (or Modernize _) to update your code (e.g. ``pip install future ``)
3737#. Use Pylint _ to help make sure you don't regress on your Python 3 support
3838 (``pip install pylint ``)
3939#. Use caniusepython3 _ to find out which of your dependencies are blocking your
4040 use of Python 3 (``pip install caniusepython3 ``)
4141#. Once your dependencies are no longer blocking you, use continuous integration
4242 to make sure you stay compatible with Python 2 & 3 (tox _ can help test
4343 against multiple versions of Python; ``pip install tox ``)
44-
45- If you are dropping support for Python 2 entirely, then after you learn the
46- differences between Python 2 & 3 you can run 2to3 _ over your code and skip the
47- rest of the steps outlined above.
44+ #. Consider using optional static type checking to make sure your type usage
45+ works in both Python 2 & 3 (e.g. use mypy _ to check your typing under both
46+ Python 2 & Python 3).
4847
4948
5049Details
@@ -54,7 +53,7 @@ A key point about supporting Python 2 & 3 simultaneously is that you can start
5453**today **! Even if your dependencies are not supporting Python 3 yet that does
5554not mean you can't modernize your code **now ** to support Python 3. Most changes
5655required to support Python 3 lead to cleaner code using newer practices even in
57- Python 2.
56+ Python 2 code .
5857
5958Another key point is that modernizing your Python 2 code to also support
6059Python 3 is largely automated for you. While you might have to make some API
@@ -82,12 +81,13 @@ have to import a function instead of using a built-in one, but otherwise the
8281overall transformation should not feel foreign to you.
8382
8483But you should aim for only supporting Python 2.7. Python 2.6 is no longer
85- supported and thus is not receiving bugfixes. This means **you ** will have to
86- work around any issues you come across with Python 2.6. There are also some
84+ freely upported and thus is not receiving bugfixes. This means **you ** will have
85+ to work around any issues you come across with Python 2.6. There are also some
8786tools mentioned in this HOWTO which do not support Python 2.6 (e.g., Pylint _),
8887and this will become more commonplace as time goes on. It will simply be easier
8988for you if you only support the versions of Python that you have to support.
9089
90+
9191Make sure you specify the proper version support in your ``setup.py `` file
9292--------------------------------------------------------------------------
9393
@@ -98,6 +98,7 @@ Python 3 yet you should at least have
9898also specify each major/minor version of Python that you do support, e.g.
9999``Programming Language :: Python :: 2.7 ``.
100100
101+
101102Have good test coverage
102103-----------------------
103104
@@ -106,10 +107,11 @@ to, you will want to make sure your test suite has good coverage. A good rule of
106107thumb is that if you want to be confident enough in your test suite that any
107108failures that appear after having tools rewrite your code are actual bugs in the
108109tools and not in your code. If you want a number to aim for, try to get over 80%
109- coverage (and don't feel bad if you can't easily get past 90%). If you
110+ coverage (and don't feel bad if you can't easily get passed 90%). If you
110111don't already have a tool to measure test coverage then coverage.py _ is
111112recommended.
112113
114+
113115Learn the differences between Python 2 & 3
114116-------------------------------------------
115117
@@ -127,13 +129,15 @@ Update your code
127129
128130Once you feel like you know what is different in Python 3 compared to Python 2,
129131it's time to update your code! You have a choice between two tools in porting
130- your code automatically: Modernize _ and Futurize _ . Which tool you choose will
132+ your code automatically: Futurize _ and Modernize _ . Which tool you choose will
131133depend on how much like Python 3 you want your code to be. Futurize _ does its
132134best to make Python 3 idioms and practices exist in Python 2, e.g. backporting
133135the ``bytes `` type from Python 3 so that you have semantic parity between the
134136major versions of Python. Modernize _,
135137on the other hand, is more conservative and targets a Python 2/3 subset of
136- Python, relying on six _ to help provide compatibility.
138+ Python, directly relying on six _ to help provide compatibility. As Python 3 is
139+ the future, it might be best to consider Futurize to begin adjusting to any new
140+ practices that Python 3 introduces which you are not accustomed to yet.
137141
138142Regardless of which tool you choose, they will update your code to run under
139143Python 3 while staying compatible with the version of Python 2 you started with.
@@ -153,6 +157,7 @@ the built-in ``open()`` function is off by default in Modernize). Luckily,
153157though, there are only a couple of things to watch out for which can be
154158considered large issues that may be hard to debug if not watched for.
155159
160+
156161Division
157162++++++++
158163
@@ -173,6 +178,7 @@ an object defines a ``__truediv__`` method but not ``__floordiv__`` then your
173178code would begin to fail (e.g. a user-defined class that uses ``/ `` to
174179signify some operation but not ``// `` for the same thing or at all).
175180
181+
176182Text versus binary data
177183+++++++++++++++++++++++
178184
@@ -189,7 +195,7 @@ To make the distinction between text and binary data clearer and more
189195pronounced, Python 3 did what most languages created in the age of the internet
190196have done and made text and binary data distinct types that cannot blindly be
191197mixed together (Python predates widespread access to the internet). For any code
192- that only deals with text or only binary data, this separation doesn't pose an
198+ that deals only with text or only binary data, this separation doesn't pose an
193199issue. But for code that has to deal with both, it does mean you might have to
194200now care about when you are using text compared to binary data, which is why
195201this cannot be entirely automated.
@@ -198,15 +204,15 @@ To start, you will need to decide which APIs take text and which take binary
198204(it is **highly ** recommended you don't design APIs that can take both due to
199205the difficulty of keeping the code working; as stated earlier it is difficult to
200206do well). In Python 2 this means making sure the APIs that take text can work
201- with ``unicode `` in Python 2 and those that work with binary data work with the
202- ``bytes `` type from Python 3 and thus a subset of ``str `` in Python 2 (which the
203- ``bytes `` type in Python 2 is an alias for ). Usually the biggest issue is
204- realizing which methods exist for which types in Python 2 & 3 simultaneously
207+ with ``unicode `` and those that work with binary data work with the
208+ ``bytes `` type from Python 3 (which is a subset of ``str `` in Python 2 and acts
209+ as an alias for ``bytes `` type in Python 2). Usually the biggest issue is
210+ realizing which methods exist on which types in Python 2 & 3 simultaneously
205211(for text that's ``unicode `` in Python 2 and ``str `` in Python 3, for binary
206212that's ``str ``/``bytes `` in Python 2 and ``bytes `` in Python 3). The following
207213table lists the **unique ** methods of each data type across Python 2 & 3
208214(e.g., the ``decode() `` method is usable on the equivalent binary data type in
209- either Python 2 or 3, but it can't be used by the text data type consistently
215+ either Python 2 or 3, but it can't be used by the textual data type consistently
210216between Python 2 and 3 because ``str `` in Python 3 doesn't have the method). Do
211217note that as of Python 3.5 the ``__mod__ `` method was added to the bytes type.
212218
@@ -232,22 +238,25 @@ This allows your code to work with only text internally and thus eliminates
232238having to keep track of what type of data you are working with.
233239
234240The next issue is making sure you know whether the string literals in your code
235- represent text or binary data. At minimum you should add a ``b `` prefix to any
236- literal that presents binary data. For text you should either use the
237- ``from __future__ import unicode_literals `` statement or add a ``u `` prefix to
238- the text literal.
241+ represent text or binary data. You should add a ``b `` prefix to any
242+ literal that presents binary data. For text you should add a ``u `` prefix to
243+ the text literal. (there is a :mod: `__future__ ` import to force all unspecified
244+ literals to be Unicode, but usage has shown it isn't as effective as adding a
245+ ``b `` or ``u `` prefix to all literals explicitly)
239246
240247As part of this dichotomy you also need to be careful about opening files.
241248Unless you have been working on Windows, there is a chance you have not always
242249bothered to add the ``b `` mode when opening a binary file (e.g., ``rb `` for
243250binary reading). Under Python 3, binary files and text files are clearly
244251distinct and mutually incompatible; see the :mod: `io ` module for details.
245252Therefore, you **must ** make a decision of whether a file will be used for
246- binary access (allowing binary data to be read and/or written) or text access
253+ binary access (allowing binary data to be read and/or written) or textual access
247254(allowing text data to be read and/or written). You should also use :func: `io.open `
248255for opening files instead of the built-in :func: `open ` function as the :mod: `io `
249256module is consistent from Python 2 to 3 while the built-in :func: `open ` function
250- is not (in Python 3 it's actually :func: `io.open `).
257+ is not (in Python 3 it's actually :func: `io.open `). Do not bother with the
258+ outdated practice of using :func: `codecs.open ` as that's only necessary for
259+ keeping compatibility with Python 2.5.
251260
252261The constructors of both ``str `` and ``bytes `` have different semantics for the
253262same arguments between Python 2 & 3. Passing an integer to ``bytes `` in Python 2
@@ -274,21 +283,22 @@ To summarize:
274283#. Make sure that your code that works with text also works with ``unicode `` and
275284 code for binary data works with ``bytes `` in Python 2 (see the table above
276285 for what methods you cannot use for each type)
277- #. Mark all binary literals with a ``b `` prefix, use a ``u `` prefix or
278- :mod: ` __future__ ` import statement for text literals
286+ #. Mark all binary literals with a ``b `` prefix, textual literals with a ``u ``
287+ prefix
279288#. Decode binary data to text as soon as possible, encode text as binary data as
280289 late as possible
281290#. Open files using :func: `io.open ` and make sure to specify the ``b `` mode when
282291 appropriate
283- #. Be careful when indexing binary data
292+ #. Be careful when indexing into binary data
284293
285294
286295Use feature detection instead of version detection
287296++++++++++++++++++++++++++++++++++++++++++++++++++
297+
288298Inevitably you will have code that has to choose what to do based on what
289299version of Python is running. The best way to do this is with feature detection
290300of whether the version of Python you're running under supports what you need.
291- If for some reason that doesn't work then you should make the version check is
301+ If for some reason that doesn't work then you should make the version check be
292302against Python 2 and not Python 3. To help explain this, let's look at an
293303example.
294304
@@ -340,14 +350,12 @@ at least the following block of code at the top of it::
340350 from __future__ import absolute_import
341351 from __future__ import division
342352 from __future__ import print_function
343- from __future__ import unicode_literals
344353
345354You can also run Python 2 with the ``-3 `` flag to be warned about various
346355compatibility issues your code triggers during execution. If you turn warnings
347356into errors with ``-Werror `` then you can make sure that you don't accidentally
348357miss a warning.
349358
350-
351359You can also use the Pylint _ project and its ``--py3k `` flag to lint your code
352360to receive warnings when your code begins to deviate from Python 3
353361compatibility. This also prevents you from having to run Modernize _ or Futurize _
@@ -364,22 +372,23 @@ care about whether your dependencies have also been ported. The caniusepython3_
364372project was created to help you determine which projects
365373-- directly or indirectly -- are blocking you from supporting Python 3. There
366374is both a command-line tool as well as a web interface at
367- https://caniusepython3.com .
375+ https://caniusepython3.com.
368376
369377The project also provides code which you can integrate into your test suite so
370378that you will have a failing test when you no longer have dependencies blocking
371379you from using Python 3. This allows you to avoid having to manually check your
372380dependencies and to be notified quickly when you can start running on Python 3.
373381
382+
374383Update your ``setup.py `` file to denote Python 3 compatibility
375384--------------------------------------------------------------
376385
377386Once your code works under Python 3, you should update the classifiers in
378387your ``setup.py `` to contain ``Programming Language :: Python :: 3 `` and to not
379- specify sole Python 2 support. This will tell
380- anyone using your code that you support Python 2 **and ** 3. Ideally you will
381- also want to add classifiers for each major/minor version of Python you now
382- support.
388+ specify sole Python 2 support. This will tell anyone using your code that you
389+ support Python 2 **and ** 3. Ideally you will also want to add classifiers for
390+ each major/minor version of Python you now support.
391+
383392
384393Use continuous integration to stay compatible
385394---------------------------------------------
@@ -404,20 +413,17 @@ don't accidentally break Python 2 or 3 compatibility regardless of which version
404413you typically run your tests under while developing.
405414
406415
407- Dropping Python 2 support completely
408- ====================================
409-
410- If you are able to fully drop support for Python 2, then the steps required
411- to transition to Python 3 simplify greatly.
412-
413- #. Update your code to only support Python 2.7
414- #. Make sure you have good test coverage (coverage.py _ can help)
415- #. Learn the differences between Python 2 & 3
416- #. Use 2to3 _ to rewrite your code to run only under Python 3
416+ Consider using optional static type checking
417+ --------------------------------------------
417418
418- After this your code will be fully Python 3 compliant but in a way that is not
419- supported by Python 2. You should also update the classifiers in your
420- ``setup.py `` to contain ``Programming Language :: Python :: 3 :: Only ``.
419+ Another way to help port your code is to use a static type checker like
420+ mypy _ or pytype _ on your code. These tools can be used to analyze your code as
421+ if it's being run under Python 2, then you can run the tool a second time as if
422+ your code is running under Python 3. By running a static type checker twice like
423+ this you can discover if you're e.g. misusing binary data type in one version
424+ of Python compared to another. If you add optional type hints to your code you
425+ can also explicitly state whether your APIs use textual or binary data, helping
426+ to make sure everything functions as expected in both versions of Python.
421427
422428
423429.. _2to3 : https://docs.python.org/3/library/2to3.html
@@ -428,13 +434,19 @@ supported by Python 2. You should also update the classifiers in your
428434.. _importlib : https://docs.python.org/3/library/importlib.html#module-importlib
429435.. _importlib2 : https://pypi.python.org/pypi/importlib2
430436.. _Modernize : https://python-modernize.readthedocs.org/en/latest/
437+ .. _mypy : http://mypy-lang.org/
431438.. _Porting to Python 3 : http://python3porting.com/
432439.. _Pylint : https://pypi.python.org/pypi/pylint
440+
433441.. _Python 3 Q & A : https://ncoghlan-devs-python-notes.readthedocs.org/en/latest/python3/questions_and_answers.html
434442
443+ .. _pytype : https://github.com/google/pytype
435444.. _python-future : http://python-future.org/
436445.. _python-porting : https://mail.python.org/mailman/listinfo/python-porting
437446.. _six : https://pypi.python.org/pypi/six
438447.. _tox : https://pypi.python.org/pypi/tox
439448.. _trove classifier : https://pypi.python.org/pypi?%3Aaction=list_classifiers
449+
440450.. _"What's New" : https://docs.python.org/3/whatsnew/index.html
451+
452+ .. _Why Python 3 exists : http://www.snarky.ca/why-python-3-exists
0 commit comments