Skip to content

Latest commit

 

History

History
116 lines (79 loc) · 3.52 KB

targeting_python_2_3.rst

File metadata and controls

116 lines (79 loc) · 3.52 KB

Targeting Python 2+3

In a lot of cases you might want to develop programs which can be run in both Python 2+ and 3+.

Just imagine that you have a very popular Python module which is use by hundreds of people but not all of them have Python 2 or 3. In that case you have two choices. The first one is to distribute 2 modules, one for Python 2 and the other for Python 3. The other choice is to modify your current code and make is compatible with both Python 2 and 3.

In this section I am going to highlight some of the tricks which you can employ to make a script compatible with both of them.

Future imports

The first and most important method is to use __future__ imports. It allows you to import Python 3 functionality in Python 2. Here is an example:

  • Context managers were new in Python 2.6+. For using them in Python 2.5 you can use:
from __future__ import with_statement
  • print function

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

First tell me how you import packages in your script ? Most of us do this :

import foo
# or
from foo import bar

Do you know that you can do something like this as well?

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

So let me explain the above code a little. We are wrapping our importing code in a try except clause. We are doing it because in Python 2 there is no urllib.request module and will result in an ImportError. The functionality of urllib.request is provided by urllib2 module in Python 2. So now when in Python 2 we try to import urllib.request and get an ImportError we tell Python to import urllib2 instead.

The final thing you need to know about is the as keyword. It is mapping the imported module to urllib_request. So that now all of the Classes and methods of urllib2 are available to us by urllib_request.

Obsolete Python 2 builtins

Another thing to keep in mind is that there are 12 Python 2 builtins which have been removed from Python 3. Make sure that you don't use them in Python 2 as well in order to make your code compatible with Python 3. Here is a way to enforce you to abandon these 12 builtins in Python 2 as well.

from future.builtins.disabled import *

Now whenever you try to use the modules which are abandoned in Python 3, it raises a NameError like 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 in the wild which provide Python 3 functionality in Python 2. For instance we have:

  • enum pip install enum34
  • singledispatch pip install singledispatch
  • pathlib pip install pathlib

For further reading, the Python documentation has a comprehensive guide of steps you need to take to make your code compatible with both Python 2 and 3.