See More

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 it 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 are a couple examples: Context managers were new in Python 2.6+. For using them in Python 2.5 you can use: .. code:: python 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__``: .. code:: python print # Output: from __future__ import print_function print(print) # Output: **Dealing with module renaming** First, tell me how you import packages in your script ? Most of us do this : .. code:: python import foo # or from foo import bar Do you know that you can do something like this as well? .. code:: python 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 : .. code:: python 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 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 final thing you need to know about is the ``as`` keyword. It is mapping the imported module to ``urllib_request``. So that all of the classes and methods within ``urllib2`` are available to us via the alias ``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 in order to make your code compatible with Python 3. Here is a way to enforce that you abandon these 12 builtins in Python 2 as well: .. code:: python 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: .. code:: python 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.