Easy, Clean, Reliable Python 2/3 Compatibility
Easy, Clean, Reliable Python 2/3 Compatibility
Easy, Clean, Reliable Python 2/3 Compatibility
Overview
Cheat Sheet
FAQ
Contents
Page
Search
pdfcrowd.com
Byte-string literals
basestring
unicode
StringIO
Imports relative to a package
Dictionaries
Iterating through dict keys/values/items
dict keys/values/items as a list
Custom class behaviour
Custom iterators
Custom __str__ methods
Custom __nonzero__ vs __bool__ method:
Lists versus iterators
xrange
range
map
imap
zip, izip
filter, ifilter
Other builtins
File IO with open()
reduce()
raw_input()
input()
open in browser PRO version
pdfcrowd.com
file()
exec
execfile()
unichr()
intern()
apply()
chr()
cmp()
reload()
Standard library
dbm modules
commands / subprocess modules
subprocess.check_output()
collections: Counter and OrderedDict
StringIO module
http module
xmlrpc module
html escaping and entities
html parsing
urllib module
Tkinter
socketserver
copy_reg, copyreg
open in browser PRO version
pdfcrowd.com
configparser
queue
repr, reprlib
UserDict, UserList, UserString
itertools: filterfalse, zip_longest
Imports
What else you need to know
Automatic conversion to Py2/3
Frequently Asked Questions (FAQ)
Standard library incompatibilities
Older interfaces
Changes in previous versions
Licensing and credits
API Reference (in progress)
pdfcrowd.com
Setup
The imports below refer to these pip -installable packages on PyPI:
import
import
import
import
future
builtins
past
six
#
#
#
#
pip
pip
pip
pip
install
install
install
install
future
future
future
six
pdfcrowd.com
print
# Python 2 only:
print 'Hello'
# Python 2 and 3:
print('Hello')
To print multiple strings, import print_function to prevent Py2 from interpreting it as a tuple:
# Python 2 only:
print 'Hello', 'Guido'
# Python 2 and 3:
from __future__ import print_function
print('Hello', 'Guido')
# Python 2 only:
print >> sys.stderr, 'Hello'
# Python 2 and 3:
from __future__ import print_function
print('Hello', file=sys.stderr)
# Python 2 only:
open in browser PRO version
pdfcrowd.com
print 'Hello',
# Python 2 and 3:
from __future__ import print_function
print('Hello', end='')
Raising exceptions
# Python 2 only:
raise ValueError, "dodgy value"
# Python 2 and 3:
raise ValueError("dodgy value")
# Python 3 only:
raise ValueError("dodgy value").with_traceback()
pdfcrowd.com
# Python 3 only
class FileDatabase:
def __init__(self, filename):
try:
self.file = open(filename)
except IOError as exc:
raise DatabaseError('failed to open') from exc
# Python 2 and 3:
from future.utils import raise_from
class FileDatabase:
def __init__(self, filename):
open in browser PRO version
pdfcrowd.com
try:
self.file = open(filename)
except IOError as exc:
raise_from(DatabaseError('failed to open'), exc)
Catching exceptions
# Python 2 only:
try:
...
except ValueError, e:
...
# Python 2 and 3:
try:
...
except ValueError as e:
...
Division
open in browser PRO version
pdfcrowd.com
# Python 2 and 3:
assert 2 // 3 == 0
# Python 2 and 3:
from __future__ import division
assert 3 / 2 == 1.5
# Python 2 and 3:
from past.utils import old_div
a = old_div(b, c)
pdfcrowd.com
Long integers
Short integers are gone in Python 3 and long has become int (without the trailing L in the repr ).
# Python 2 only
k = 9223372036854775808L
# Python 2 and 3:
k = 9223372036854775808
# Python 2 only
bigint = 1L
# Python 2 and 3
from builtins import int
bigint = int(1)
pdfcrowd.com
if isinstance(x, int):
...
Octal constants
0644
# Python 2 only
0o644
# Python 2 and 3
Backtick repr
`x`
# Python 2 only
repr(x)
# Python 2 and 3
Metaclasses
class BaseForm(object):
pass
pdfcrowd.com
class FormType(type):
pass
# Python 2 only:
class Form(BaseForm):
__metaclass__ = FormType
pass
# Python 3 only:
class Form(BaseForm, metaclass=FormType):
pass
# Python 2 and 3:
from six import with_metaclass
# or
from future.utils import with_metaclass
class Form(with_metaclass(FormType, BaseForm)):
pass
pdfcrowd.com
# Python 2 only
s1 = 'The Zen of Python'
s2 = u'\n'
# Python 2 and 3
s1 = u'The Zen of Python'
s2 = u'\n'
The futurize and python-modernize tools do not currently offer an option to do this automatically.
If you are writing code for a new project or new codebase, you can use this idiom to make all string literals in a
module unicode strings:
# Python 2 and 3
from __future__ import unicode_literals
# at top of module
Byte-string literals
# Python 2 only
s = 'This must be a byte-string'
# Python 2 and 3
s = b'This must be a byte-string'
To loop over a byte-string with possible high-bit characters, obtaining each character as a byte-string of length 1:
open in browser PRO version
pdfcrowd.com
# Python 2 only:
for bytechar in 'byte-string with high-bit chars like \xf9':
...
# Python 3 only:
for myint in b'byte-string with high-bit chars like \xf9':
bytechar = bytes([myint])
# Python 2 and 3:
from builtins import bytes
for myint in bytes(b'byte-string with high-bit chars like \xf9'):
bytechar = bytes([myint])
As an alternative, chr() and .encode('latin-1') can be used to convert an int into a 1-char byte string:
# Python 3 only:
for myint in b'byte-string with high-bit chars like \xf9':
char = chr(myint)
# returns a unicode string
bytechar = char.encode('latin-1')
# Python 2 and 3:
from builtins import bytes, chr
for myint in bytes(b'byte-string with high-bit chars like \xf9'):
char = chr(myint)
# returns a unicode string
bytechar = char.encode('latin-1')
# forces returning a byte str
basestring
# Python 2 only:
open in browser PRO version
pdfcrowd.com
a = u'abc'
b = 'def'
assert (isinstance(a, basestring) and isinstance(b, basestring))
# Python 2 and 3: alternative 1
from past.builtins import basestring
a = u'abc'
b = b'def'
assert (isinstance(a, basestring) and isinstance(b, basestring))
unicode
# Python 2 only:
templates = [u"blog/blog_post_detail_%s.html" % unicode(slug)]
pdfcrowd.com
StringIO
# Python 2 only:
from StringIO import StringIO
# or:
from cStringIO import StringIO
# Python 2 and 3:
from io import BytesIO
from io import StringIO
pdfcrowd.com
import submodule2
# Python 2 and 3:
from . import submodule2
# Python 2 and 3:
# To make Py2 code safer (more like Py3) by preventing
# implicit relative imports, you can also add this to the top:
from __future__ import absolute_import
Dictionaries
heights = {'Fred': 175, 'Anne': 166, 'Joe': 192}
# Python 2 and 3:
for key in heights:
...
pdfcrowd.com
# Python 2 only:
for value in heights.itervalues():
...
# Idiomatic Python 3
for value in heights.values():
...
pdfcrowd.com
# inefficient on Py2
# Python 2 and 3:
open in browser PRO version
pdfcrowd.com
keylist = list(heights)
assert isinstance(keylist, list)
# inefficient on Py2
pdfcrowd.com
valuelist = list(itervalues(heights))
# inefficient on Py2
pdfcrowd.com
def next(self):
# Py2-style
return self._iter.next().upper()
def __iter__(self):
return self
itr = Upper('hello')
assert itr.next() == 'H'
# Py2-style
assert list(itr) == list('ELLO')
pdfcrowd.com
self._iter = iter(iterable)
def __next__(self):
return next(self._iter).upper()
def __iter__(self):
return self
itr = Upper('hello')
assert next(itr) == 'H'
assert list(itr) == list('ELLO')
# Python 2 and 3:
from future.utils import python_2_unicode_compatible
@python_2_unicode_compatible
class MyClass(object):
def __str__(self):
return u'Unicode string: \u5b54\u5b50'
open in browser PRO version
pdfcrowd.com
a = MyClass()
print(a)
# prints string encoded as utf-8 on Py2
Unicode string:
# Python 2 and 3:
from builtins import object
class AllOrNothing(object):
def __init__(self, l):
self.l = l
def __bool__(self):
return all(self.l)
container = AllOrNothing([0, 100, 200])
assert not bool(container)
open in browser PRO version
pdfcrowd.com
range
# Python 2 only
mylist = range(5)
assert mylist == [0, 1, 2, 3, 4]
pdfcrowd.com
mylist = list(range(5))
assert mylist == [0, 1, 2, 3, 4]
map
# Python 2 only:
mynewlist = map(f, myoldlist)
assert mynewlist == [f(x) for x in myoldlist]
pdfcrowd.com
pdfcrowd.com
imap
# Python 2 only:
from itertools import imap
myiter = imap(func, myoldlist)
assert isinstance(myiter, iter)
# Python 3 only:
myiter = map(func, myoldlist)
assert isinstance(myiter, iter)
pdfcrowd.com
zip, izip
As above with zip and itertools.izip .
filter, ifilter
As above with filter and itertools.ifilter too.
Other builtins
File IO with open()
# Python 2 only
f = open('myfile.txt')
data = f.read()
text = data.decode('utf-8')
# as a byte string
pdfcrowd.com
reduce()
# Python 2 only:
assert reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) == 1+2+3+4+5
# Python 2 and 3:
from functools import reduce
assert reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) == 1+2+3+4+5
raw_input()
# Python 2 only:
name = raw_input('What is your name? ')
assert isinstance(name, str)
# native str
# Python 2 and 3:
from builtins import input
name = input('What is your name? ')
assert isinstance(name, str)
# native str on Py2 and Py3
input()
# Python 2 only:
open in browser PRO version
pdfcrowd.com
# Python 2 and 3
from builtins import input
eval(input("Type something safe please: "))
file()
# Python 2 only:
f = file(pathname)
# Python 2 and 3:
f = open(pathname)
# But preferably, use this:
from io import open
f = open(pathname, 'rb')
# if f.read() should return bytes
# or
f = open(pathname, 'rt')
# if f.read() should return unicode text
exec
# Python 2 only:
exec 'x = 10'
# Python 2 and 3:
open in browser PRO version
pdfcrowd.com
exec('x = 10')
# Python 2 only:
g = globals()
exec 'x = 10' in g
# Python 2 and 3:
g = globals()
exec('x = 10', g)
# Python 2 only:
l = locals()
exec 'x = 10' in g, l
# Python 2 and 3:
exec('x = 10', g, l)
execfile()
# Python 2 only:
execfile('myfile.py')
pdfcrowd.com
unichr()
# Python 2 only:
assert unichr(8364) == ''
# Python 3 only:
assert chr(8364) == ''
# Python 2 and 3:
from builtins import chr
assert chr(8364) == ''
intern()
# Python 2 only:
intern('mystring')
# Python 3 only:
from sys import intern
intern('mystring')
open in browser PRO version
pdfcrowd.com
apply()
args = ('a', 'b')
kwargs = {'kwarg1': True}
pdfcrowd.com
# Python 2 only:
apply(f, args, kwargs)
chr()
# Python 2 only:
assert chr(64) == b'@'
assert chr(200) == b'\xc8'
pdfcrowd.com
cmp()
# Python 2 only:
assert cmp('a', 'b') < 0 and cmp('b', 'a') > 0 and cmp('c', 'c') == 0
reload()
# Python 2 only:
reload(mymodule)
open in browser PRO version
pdfcrowd.com
# Python 2 and 3
from imp import reload
reload(mymodule)
Standard library
dbm modules
# Python 2 only
import anydbm
import whichdb
import dbm
import dumbdbm
import gdbm
# Python 2 and 3: alternative 1
from future import standard_library
standard_library.install_aliases()
import
import
import
import
dbm
dbm.ndbm
dbm.dumb
dbm.gnu
pdfcrowd.com
subprocess.check_output()
# Python 2.7 and above
from subprocess import check_output
# Python 2.6 and above: alternative 1
from future.moves.subprocess import check_output
# Python 2.6 and above: alternative 2
from future import standard_library
standard_library.install_aliases()
from subprocess import check_output
open in browser PRO version
pdfcrowd.com
StringIO module
# Python 2 only
from StringIO import StringIO
from cStringIO import StringIO
# Python 2 and 3
from io import BytesIO
# and refactor StringIO() calls to BytesIO() if passing byte-strings
http module
open in browser PRO version
pdfcrowd.com
# Python 2 only:
import httplib
import Cookie
import cookielib
import BaseHTTPServer
import SimpleHTTPServer
import CGIHttpServer
# Python 2 and 3 (after ``pip install future``):
import http.client
import http.cookies
import http.cookiejar
import http.server
xmlrpc module
# Python 2 only:
import DocXMLRPCServer
import SimpleXMLRPCServer
# Python 2 and 3 (after ``pip install future``):
import xmlrpc.server
# Python 2 only:
import xmlrpclib
# Python 2 and 3 (after ``pip install future``):
import xmlrpc.client
pdfcrowd.com
html parsing
# Python 2 only:
from HTMLParser import HTMLParser
# Python 2 and 3 (after ``pip install future``)
from html.parser import HTMLParser
# Python 2 and 3 (alternative 2):
from future.moves.html.parser import HTMLParser
urllib module
urllib is the hardest module to use from Python 2/3 compatible code. You may like to use Requests
(http://python-requests.org) instead.
open in browser PRO version
pdfcrowd.com
# Python 2 only:
from urlparse import urlparse
from urllib import urlencode
from urllib2 import urlopen, Request, HTTPError
# Python 3 only:
from urllib.parse import urlparse, urlencode
from urllib.request import urlopen, Request
from urllib.error import HTTPError
pdfcrowd.com
from
from
from
# or
from
from
from
Tkinter
# Python 2 only:
import Tkinter
import Dialog
import FileDialog
import ScrolledText
import SimpleDialog
import Tix
import Tkconstants
import Tkdnd
open in browser PRO version
pdfcrowd.com
import
import
import
import
import
import
import
tkColorChooser
tkCommonDialog
tkFileDialog
tkFont
tkMessageBox
tkSimpleDialog
ttk
socketserver
# Python 2 only:
import SocketServer
open in browser PRO version
pdfcrowd.com
copy_reg, copyreg
# Python 2 only:
import copy_reg
# Python 2 and 3 (after ``pip install future``):
import copyreg
configparser
# Python 2 only:
from ConfigParser import ConfigParser
# Python 2 and 3 (after ``pip install future``):
from configparser import ConfigParser
queue
# Python 2 only:
from Queue import Queue, heapq, deque
# Python 2 and 3 (after ``pip install future``):
from queue import Queue, heapq, deque
pdfcrowd.com
repr, reprlib
# Python 2 only:
from repr import aRepr, repr
# Python 2 and 3 (after ``pip install future``):
from reprlib import aRepr, repr
pdfcrowd.com
Back to top
pdfcrowd.com