- Notifications
You must be signed in to change notification settings - Fork294
Easy, clean, reliable Python 2/3 compatibility
License
PythonCharmers/python-future
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
python-future
is the missing compatibility layer between Python 2 andPython 3. It allows you to use a single, clean Python 3.x-compatiblecodebase to support both Python 2 and Python 3 with minimal overhead.
It providesfuture
andpast
packages with backports and forwardports of features from Python 3 and 2. It also comes withfuturize
andpasteurize
, customized 2to3-based scripts that helps you to converteither Py2 or Py3 code easily to support both Python 2 and 3 in a singleclean Py3-style codebase, module by module.
Thepython-future
project has been downloaded over 1.7 billion times.
Thepython-future
project was created in 2013 to attempt to save Python fromthe schism of version incompatibility that was threatening to tear apart thelanguage (as Perl 6 contributed to the death of Perl).
That time is now past. Thanks to a huge porting effort across the Pythoncommunity, Python 3 eventually thrived. Python 2 reached its end of life in2020 and thepython-future
package should no longer be necessary. Use it tohelp with porting legacy code to Python 3 but don't depend on it for new code.
future.builtins
package (also available asbuiltins
on Py2) providesbackports and remappings for 20 builtins with different semantics on Py3versus Py2- support for directly importing 30 standard library modules undertheir Python 3 names on Py2
- support for importing the other 14 refactored standard library modulesunder their Py3 names relatively cleanly via
future.standard_library
andfuture.moves
past.builtins
package provides forward-ports of 19 Python 2 types andbuiltin functions. These can aid with per-module code migrations.past.translation
package supports transparent translation of Python 2modules to Python 3 upon import. [This feature is currently in alpha.]- 1000+ unit tests, including many from the Py3.3 source tree.
futurize
andpasteurize
scripts based on2to3
and parts of3to2
andpython-modernize
, for automatic conversion from either Py2or Py3 to a clean single-source codebase compatible with Python 2.6+ andPython 3.3+.- a curated set of utility functions and decorators in
future.utils
andpast.utils
selected from Py2/3 compatibility interfaces from projectslikesix
,IPython
,Jinja2
,Django
, andPandas
. - support for the
surrogateescape
error handler when encoding anddecoding the backportedstr
andbytes
objects. [This feature iscurrently in alpha.] - support for pre-commit hooks
Replacements for Py2's built-in functions and types are designed to be importedat the top of each Python module together with Python's built-in__future__
statements. For example, this code behaves identically on Python 2.6/2.7 afterthese imports as it does on Python 3.3+:
from __future__importabsolute_import,division,print_functionfrombuiltinsimport (bytes,str,open,super,range,zip,round,input,int,pow,object)# Backported Py3 bytes objectb=bytes(b'ABCD')assertlist(b)== [65,66,67,68]assertrepr(b)=="b'ABCD'"# These raise TypeErrors:# b + u'EFGH'# bytes(b',').join([u'Fred', u'Bill'])# Backported Py3 str objects=str(u'ABCD')asserts!=bytes(b'ABCD')assertisinstance(s.encode('utf-8'),bytes)assertisinstance(b.decode('utf-8'),str)assertrepr(s)=="'ABCD'"# consistent repr with Py3 (no u prefix)# These raise TypeErrors:# bytes(b'B') in s# s.find(bytes(b'A'))# Extra arguments for the open() functionf=open('japanese.txt',encoding='utf-8',errors='replace')# New zero-argument super() function:classVerboseList(list):defappend(self,item):print('Adding an item')super().append(item)# New iterable range object with slicing supportforiinrange(10**15)[:10]:pass# Other iterators: map, zip, filtermy_iter=zip(range(3), ['a','b','c'])assertmy_iter!=list(my_iter)# The round() function behaves as it does in Python 3, using# "Banker's Rounding" to the nearest even last digit:assertround(0.1250,2)==0.12# input() replaces Py2's raw_input() (with no eval()):name=input('What is your name? ')print('Hello '+name)# pow() supports fractional exponents of negative numbers like in Py3:z=pow(-1,0.5)# Compatible output from isinstance() across Py2/3:assertisinstance(2**64,int)# long integersassertisinstance(u'blah',str)assertisinstance('blah',str)# only if unicode_literals is in effect# Py3-style iterators written as new-style classes (subclasses of# future.types.newobject) are automatically backward compatible with Py2:classUpper(object):def__init__(self,iterable):self._iter=iter(iterable)def__next__(self):# note the Py3 interfacereturnnext(self._iter).upper()def__iter__(self):returnselfassertlist(Upper('hello'))==list('HELLO')
There is also support for renamed standard library modules. The recommendedinterface works like this:
# Many Py3 module names are supported directly on both Py2.x and 3.x:fromhttp.clientimportHttpConnectionimporthtml.parserimportqueueimportxmlrpc.client# Refactored modules with clashing names on Py2 and Py3 are supported# as follows:fromfutureimportstandard_librarystandard_library.install_aliases()# Then, for example:fromitertoolsimportfilterfalse,zip_longestfromurllib.requestimporturlopenfromcollectionsimportChainMapfromcollectionsimportUserDict,UserList,UserStringfromsubprocessimportgetoutput,getstatusoutputfromcollectionsimportCounter,OrderedDict# backported to Py2.6
python-future
comes with two scripts calledfuturize
andpasteurize
to aid in making Python 2 code or Python 3 code compatible withboth platforms (Py2/3). It is based on 2to3 and uses fixers fromlib2to3
,lib3to2
, andpython-modernize
, as well as custom fixers.
futurize
passes Python 2 code through all the appropriate fixers to turn itinto valid Python 3 code, and then adds__future__
andfuture
packageimports so that it also runs under Python 2.
For conversions from Python 3 code to Py2/3, use thepasteurize
scriptinstead. This converts Py3-only constructs (e.g. new metaclass syntax) toPy2/3 compatible constructs and adds__future__
andfuture
imports tothe top of each module.
In both cases, the result should be relatively clean Py3-style code that runsmostly unchanged on both Python 2 and Python 3.
For example, runningfuturize -w mymodule.py
turns this Python 2 code:
importQueuefromurllib2importurlopendefgreet(name):print'Hello',printnameprint"What's your name?",name=raw_input()greet(name)
into this code which runs on both Py2 and Py3:
from __future__importprint_functionfromfutureimportstandard_librarystandard_library.install_aliases()frombuiltinsimportinputimportqueuefromurllib.requestimporturlopendefgreet(name):print('Hello',end=' ')print(name)print("What's your name?",end=' ')name=input()greet(name)
The first four lines have no effect under Python 3 and can be removed fromthe codebase when Python 2 compatibility is no longer required.
See:ref:`forwards-conversion` and:ref:`backwards-conversion` for more details.
Thepast
package can automatically translate some simple Python 2modules to Python 3 upon import. The goal is to support the "long tail" ofreal-world Python 2 modules (e.g. on PyPI) that have not been ported yet. Forexample, here is how to use a Python 2-only package calledplotrique
onPython 3. First install it:
$ pip3 install plotrique==0.2.5-7 --no-compile# to ignore SyntaxErrors
(or usepip
if this points to your Py3 environment.)
Then pass a whitelist of module name prefixes to theautotranslate()
function.Example:
$ python3>>> from past.translation import autotranslate>>> autotranslate(['plotrique'])>>> import plotrique
This transparently translates and runs theplotrique
module and anysubmodules in theplotrique
package thatplotrique
imports.
This is intended to help you migrate to Python 3 without the need for allyour code's dependencies to support Python 3 yet. It should be used as alast resort; ideally Python 2-only dependencies should be portedproperly to a Python 2/3 compatible codebase using a tool likefuturize
and the changes should be pushed to the upstream project.
Note: the auto-translation feature is still in alpha; it needs more testing anddevelopment, and will likely never be perfect.
Pre-commit is a framework for managing and maintainingmulti-language pre-commit hooks.
In case you need to port your project from Python 2 to Python 3, you might considerusing such hook during the transition period.
First:
$ pip install pre-commit
and then in your project's directory:
$ pre-commit install
Next, you need to add this entry to your.pre-commit-config.yaml
-repo:https://github.com/PythonCharmers/python-futurerev:masterhooks: -id:futurizeargs:[--both-stages]
Theargs
part is optional, by default only stage1 is applied.
Author: | Ed Schofield, Jordan M. Adler, et al |
---|---|
Copyright: | 2013-2024 Python Charmers, Australia. |
Sponsors: | Python Charmers:https://pythoncharmers.com Pinteresthttps://opensource.pinterest.com |
Licence: | MIT. See |
Other credits: | Seehere. |
See the docshere.
If you are new to Python-Future, check out theQuickstart Guide.
For an update on changes in the latest version, see theWhat's New page.
About
Easy, clean, reliable Python 2/3 compatibility
Resources
License
Security policy
Uh oh!
There was an error while loading.Please reload this page.