Targeting Python 2 + 3

To develop programs which can be run in both Python 2+ and 3+.

You have 2 choices:

  1. Distribute 2 modules, one for Python 2 and the other for Python 3.

  2. Modify your current code and make it compatible with both Python 2 and 3.

Tricks which you can employ to make a script compatible with both of them:

Future imports

__future__ imports allow you to import Python 3 functionality in Python 2.

Examples:

Context managers were new in Python 2.6+. For using them in Python 2.5 you can use:

from __future__ import with_statement

print was changed to a function in Python 3. If you want to use it in Python 2 you can import it from __future__:

print
# Output:

from __future__ import print_function
print(print)
# Output: <built-in function print>

Dealing with module renaming

Most of us import packages like this :

import foo
# or
from foo import bar

But you can also do this:

import foo as foo

I know its function is the same as the above listed code but it is vital for making your script compatible with Python 2 and 3. Now examine the code below :

try:
    import urllib.request as urllib_request  # for Python 3
except ImportError:
    import urllib2 as urllib_request  # for Python 2

We are wrapping our importing code in a try/exceptclause. We are doing it because in Python 2 there is no urllib.request module so this would result in an ImportError. The functionality of urllib.request is provided by the urllib2 module in Python 2. So, when using Python 2, we try to import urllib.request and if we get an ImportError then we tell Python to import urllib2 instead.

The as keyword is mapping the imported module to urllib_requestso that all of the classes and methods within urllib2 are available to us via the alias urllib_request.

Obsolete Python 2 builtins

There are 12 Python 2 builtins which have been removed from Python 3. Make sure that you don’t use them in Python 2 in order to make your code compatible with Python 3.

To enforce that you abandon these 12 builtins in Python 2:

from future.builtins.disabled import *

Now whenever you try to use the modules which are abandoned in Python 3, it raises a NameErrorlike this:

from future.builtins.disabled import *

apply()
# Output: NameError: obsolete Python 2 builtin apply is disabled

External standard-library backports

There are a few packages which provide Python 3 functionality in Python 2:

  • enum pip install enum34

  • singledispatch pip install singledispatch

  • pathlib pip install pathlib

Further reading

Comprehensive guide to make your code compatible with both Python 2 and 3.

Last updated