# python-future: a compatibility layer whose own README tells you not to depend on it

> python-future provides the future and past packages, backports of Python 3 builtins and standard library modules for Python 2, plus futurize and pasteurize, 2to3 based scripts that convert either direction. The project states that Python 2 reached end of life in 2020, that the package should no longer be necessary, and that you should use it to help port legacy code but not depend on it for new code.

**PythonCharmers/python-future** — Easy, clean, reliable Python 2/3 compatibility

- Repository: https://github.com/PythonCharmers/python-future
- Website: http://python-future.org
- Stars: 1,192 · Forks: 291
- Language: Python
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/pythoncharmers-python-future

## The Status section, which is the most important part of the README

The project was created in 2013 to attempt to save Python from the schism of version incompatibility that was threatening to tear apart the language, with a parenthetical comparison to Perl 6 contributing to the death of Perl. Then the README says that time is now past. Thanks to a huge porting effort across the Python community, Python 3 eventually thrived, Python 2 reached its end of life in 2020, and the python-future package should no longer be necessary. The instruction is explicit: use it to help with porting legacy code to Python 3 but do not depend on it for new code. That is unusual candour for a library README, and it should shape the whole evaluation. The package has been downloaded over 1.7 billion times, the licence is MIT, and the last push to the repository was on 2026-07-24.

## What the two packages actually give you

The future.builtins package, also available as builtins on Python 2, provides backports and remappings for 20 builtins with different semantics on Python 3 versus Python 2. The past.builtins package provides forward-ports of 19 Python 2 types and builtin functions, and these can aid with per-module code migrations. The standard library side is handled in two parts: support for directly importing 30 standard library modules under their Python 3 names on Python 2, and support for importing the other 14 refactored standard library modules under their Python 3 names relatively cleanly via future.standard_library and future.moves. The two directions exist for two different strategies, forward-porting when you are moving to Python 3 and need Python 3 semantics in a Python 2 environment during the transition, and back-porting when you are moving code from Python 2 to Python 3 but have a large body of Python 2 idioms you want to keep working in the meantime.

## The import style, and why the __future__ import comes first

The replacements for Python 2's built-in functions and types are designed to be imported at the top of each Python module together with Python's own __future__ statements, and the README shows the pattern explicitly with absolute_import, division and print_function, then the builtins import listing bytes, str, open, super, range, zip, round, input, int, pow and object. The example then asserts behaviours that differ between the versions, that the backported bytes object gives the same list of byte values and the same repr, that the backported str is not equal to the bytes object, that extra arguments to open are accepted, that a zero-argument super() works in a subclass, that range returns an iterable object with slicing, that round uses banker's rounding, that input replaces raw_input without eval, that pow supports fractional exponents of negative numbers, and that isinstance works across the two versions for long integers and unicode. The last example shows a Python 3 style iterator written as a new-style class, with __next__ rather than next, and it is automatically backward compatible on Python 2 when it subclasses future.types.newobject.

```python
from __future__ import absolute_import, division, print_function
from builtins import (bytes, str, open, super, range,
                      zip, round, input, int, pow, object)

# Backported Py3 bytes object
b = bytes(b'ABCD')
assert list(b) == [65, 66, 67, 68]
assert repr(b) == "b'ABCD'"

# New zero-argument super() function:
class VerboseList(list):
    def append(self, item):
        print('Adding an item')
        super().append(item)

# New iterable range object with slicing support
for i in range(10**15)[:10]:
    pass
```

## Renamed standard library modules, and the aliases trick

There is a second layer for the standard library, and it works in two ways. Many Python 3 module names are supported directly on both Python 2 and Python 3, so you can write from http.client import HttpConnection, import html.parser, import queue or import xmlrpc.client without any ceremony. The refactored modules, the ones whose names clash between the two versions, are handled by installing aliases, with from future import standard_library followed by standard_library.install_aliases(). After that you can import from itertools the filterfalse and zip_longest functions that only exist on Python 3, from urllib.request the urlopen, from collections the ChainMap and the UserDict, UserList and UserString classes, and from subprocess the getoutput and getstatusoutput functions, and also the Counter and OrderedDict which are backported to Python 2.6. The two-step form is the standard pattern in libraries that need to do work at import time, and it is the main reason the package is not a drop-in for a single import line.

```python
from future import standard_library
standard_library.install_aliases()

from itertools import filterfalse, zip_longest
from urllib.request import urlopen
from collections import ChainMap
from collections import UserDict, UserList, UserString
from subprocess import getoutput, getstatusoutput
```

## futurize and pasteurize, the automatic conversion path

python-future ships two scripts, futurize and pasteurize, to aid in making Python 2 code or Python 3 code compatible with both platforms, and they are based on 2to3 and use fixers from lib2to3, lib3to2 and python-modernize, as well as custom fixers. futurize passes Python 2 code through the fixers to make it work on both, and pasteurize does the same for code written in the Python 3 style, converting it to a style that runs on both. The output is a single-source codebase compatible with Python 2.6 and later and Python 3.3 and later. The important caveat is that this is an automated transformation, so the results need reviewing rather than accepting, and the practical approach the documentation points to is module by module, which is what the per-module framing of the past.builtins package is for.

## The alpha features and the utility layer

Two features are explicitly marked as currently in alpha, and they are the two you would think of as most convenient. past.translation supports transparent translation of Python 2 modules to Python 3 upon import, and the surrogateescape error handler is supported when encoding and decoding the backported str and bytes objects, which is what lets you round-trip undecodable bytes through text. Separately, future.utils and past.utils hold a curated set of utility functions and decorators selected from the Python 2 and 3 compatibility interfaces of projects like six, IPython, Jinja2, Django and Pandas. That curation is the point, rather than a general purpose dependency. The project also ships 1000 or more unit tests, including many taken from the Python 3.3 source tree, and it has support for pre-commit hooks.

## The repository layout and how the package is assembled

The top level of the repository shows a hybrid of old and new packaging, which is what a project that straddles Python 2 and 3 looks like. There is a setup.py with a large explicit PACKAGES list enumerating every subpackage, from future.builtins and future.types through future.standard_library, the family of future.backports packages, the future.moves packages and past, past.builtins, past.types, past.utils and past.translation, and then libfuturize and libpasteurize with their fixes subpackages, which are the fixer implementations the two scripts use. The scripts themselves sit at the top level as futurize.py and pasteurize.py. There is also a setup.cfg, a pytest.ini, a MANIFEST.in, a .pre-commit-hooks.yaml, a check_rst.sh and a test.sh, a 2.6.Dockerfile alongside a regular Dockerfile that is a slim Python image with the source added to a work directory, and a docs/ directory. The setup.py also handles the Python 2 case by adding the PEP 3108 stdlib move packages to the list when the interpreter is older than 3.0, which is the kind of conditional packaging that a dual-support library needs.

## Conclusion

python-future suits someone with a Python 2 codebase that has to keep running while it is ported, and who wants the port done module by module rather than in one risky cut. It is the wrong choice for a new project, since the package's own Status section says not to depend on it for new code, and a poor fit for a codebase that could simply be moved to Python 3, since a compatibility layer adds a dependency and an import style you will have to remove later anyway. Before adopting it, read the Status section, and if the codebase needs a staged migration, start with the futurize script on one module and review the diff, because the conversion is automated and the results still need reading.

## FAQ

### What is python-future and what does it provide?

It is a compatibility layer between Python 2 and Python 3 that lets you use a single Python 3 style codebase on both. It provides the future and past packages with backports and forward-ports of builtins and standard library modules, plus the futurize and pasteurize conversion scripts. The licence is MIT.

### Should I still use python-future for new code?

No, and the README says so directly. It states that Python 2 reached its end of life in 2020 and the package should no longer be necessary, and the instruction is to use it to help with porting legacy code to Python 3 but not to depend on it for new code.

### How do I use python-future's standard library aliases?

Import the module and call install_aliases, with from future import standard_library and standard_library.install_aliases(). After that you can import the Python 3 style names such as from itertools import filterfalse, zip_longest and from urllib.request import urlopen. Many module names, including http.client, html.parser, queue and xmlrpc.client, work directly on both versions without this step.

### What is the difference between futurize and pasteurize?

Both are 2to3 based scripts with fixers from lib2to3, lib3to2 and python-modernize plus custom fixers. futurize passes Python 2 code through to make it work on both platforms, and pasteurize does the same for code already written in the Python 3 style, producing a single-source codebase compatible with Python 2.6+ and Python 3.3+.

### Which python-future features are still in alpha?

The past.translation package, which supports transparent translation of Python 2 modules to Python 3 upon import, and the surrogateescape error handler support for the backported str and bytes objects are both documented as currently in alpha.

## Sources

- [License: MIT](https://github.com/PythonCharmers/python-future/blob/master/LICENSE)
- [Project website](http://python-future.org)
- [PythonCharmers/python-future on GitHub](https://github.com/PythonCharmers/python-future)
- [README](https://github.com/PythonCharmers/python-future/blob/master/README.md)
- [Releases](https://github.com/PythonCharmers/python-future/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pythoncharmers-python-future
