Six: Python 2 and 3 Compatibility Library
Six provides simple utilities for wrapping over differences between Python 2 and Python 3. It is intended to support codebases that work on both Python 2 and 3 without modification.
The name, "six", comes from the fact that 2*3 equals 6. Why not addition? Multiplication is more powerful, and, anyway, "five" has already been snatched away.
Six provides constants that may differ between Python versions. Ones ending _types are mostly useful as the second argument to isinstance or issubclass.
Here's example usage of the module:
import six def dispatch_types(value): if isinstance(value, six.integer_types): handle_integer(value) elif isinstance(value, six.class_types): handle_class(value) elif isinstance(value, six.string_types): handle_string(value)
Object model compatibility
Python 3 renamed the attributes of several intepreter data structures. The following accessors are available. Note that the recommended way to inspect functions and methods is the stdlib :mod:`py3:inspect` module.
A class for making portable iterators. The intention is that it be subclassed and subclasses provide a __next__ method. In Python 2, :class:`Iterator` has one method: next. It simply delegates to __next__. An alternate way to do this would be to simply alias next to __next__. However, this interacts badly with subclasses that override __next__. :class:`Iterator` is empty on Python 3. (In fact, it is just aliased to :class:`py3:object`.)
These functions smooth over operations which have different syntaxes between Python 2 and 3.
Binary and text data
Python 3 enforces the distinction between byte strings and text strings far more rigoriously than Python 2 does; binary data cannot be automatically coerced to or from text data. six provides several functions to assist in classifying string data in all Python versions.
Renamed modules and attributes compatibility
Python 3 reorganized the standard library and moved several functions to different modules. Six provides a consistent interface to them through the fake :mod:`six.moves` module. For example, to load the module for parsing HTML on Python 2 or 3, write:
from six.moves import html_parser
Similarly, to get the function to reload modules, which was moved from the builtin module to the imp module, use:
from six.moves import reload_module
For the most part, :mod:`six.moves` aliases are the names of the modules in Python 3. When the new Python 3 name is a package, the components of the name are separated by underscores. For example, html.parser becomes html_parser. In some cases where several modules have been combined, the Python 2 name is retained. This is so the appropiate modules can be found when running on Python 2. For example, BaseHTTPServer which is in http.server in Python 3 is aliased as BaseHTTPServer.
Some modules which had two implementations have been merged in Python 3. For example, cPickle no longer exists in Python 3; it was merged with pickle. In these cases, fetching the fast version will load the fast one on Python 2 and the merged module in Python 3.
The :mod:`py2:urllib`, :mod:`py2:urllib2`, and :mod:`py2:urlparse` modules have been combined in the :mod:`py3:urllib` package in Python 3. :mod:`six.moves` doesn't not support their renaming because their members have been mixed across several modules in that package.
Advanced - Customizing renames
It is possible to add additional names to the :mod:`six.moves` namespace.
Instances of the following classes can be passed to :func:`add_move`. Neither have any public members.
Create a mapping for :mod:`six.moves` called name that references different modules in Python 2 and 3. old_mod is the name of the Python 2 module. new_mod is the name of the Python 3 module.
Create a mapping for :mod:`six.moves` called name that references different attributes in Python 2 and 3. old_mod is the name of the Python 2 module. new_mod is the name of the Python 3 module. If new_attr is not given, it defaults to old_attr. If neither is given, they both default to name.