Python Language


Compatibility between Python 3 and Python 2 All Versions

Python 3.x

3.0
3.1
3.2
3.3
3.4
3.5

Python 2.x

2.3
2.4
2.5
2.6
2.7

This draft deletes the entire topic.

inline side-by-side expand all collapse all

Examples

  • 85

    The standard division symbol / operates differently between Python 2 and Python 3.

    Python 3 produces a floating point result even when both operands are integers. Meanwhile, when dividing an integer by another integer, Python 2 rounds the result down to the nearest integer (also known as taking the floor of, or rounding toward negative infinity):

             # Python 2:   Python 3:
    3 / 2    #     1          1.5
    4 / 2    #     2          2.0
    2 / 3    #     0          0.6666666666666666
    -3 / 2   #    -2         -1.5
    

    There is also the integer division symbol //, which has the same function in both languages: rounds down to the nearest integer (i.e., works the same as the / symbol from Python 2).

             # Python 2:   Python 3:
    3 // 2   #     1           1
    -3 // 2  #    -2          -2
    

    The truncating behavior was deprecated in Python 2.2, but still remains in Python 2.7 for the sake of backward compatibility. If you're writing new code in Python 2, you should enable the new division behaviour and make your code Python 3 compatible by adding from __future__ import division:

    # needs to be the first statement in a module
    from __future__ import division
    
             # Python 2  Python 3:
    3 / 2    #    1.5       1.5
    -3 / 2   #   -1.5      -1.5
    

    Note: some other programming languages use rounding toward zero (truncation) rather than rounding down (toward negative infinity) as Python does (i.e. in those languages -3 / 2 == -1). This may create confusion when porting or comparing code.


    As an alternative to from __future__ import division, one can use the normal division symbol / but make sure that at least one of the operands is a float: 3 / 2.0 == 1.5. However this is a bad practice, it is just too easy to write average = sum(items) / len(items) and forget to cast one of the arguments to float. Moreover, such cases may frequently evade notice during testing, if you test on an array containing floats, and then in production receive an array of ints. See PEP-238 for detailed rationale why the division operator was changed in Python 3 and why the old-style division should be avoided. Additionally, a code that expects that 3 / 2 == 1 wouldn't work correctly on Python 3.

  • 48

    In Python 2 there are two types generally used for text: str and unicode. A non-prefixed string literal would mean a byte string by default. In order to define a Unicode string literal you need to prefix the literal with u prefix:

    s = 'Cafe'    # type(s) == <type 'str'>
    s = u'Café'   # type(s) == <type 'unicode'>
    

    In Python 2, the type str is commonly used for both text and binary data.

    In Python 3, all text is Unicode. To create a binary data literal, you can prefix b to a string literal to define it as a byte string:

    s = 'Cafe'           # type(s) == <class 'str'>
    s = 'Café'           # type(s) == <class 'str'>
    # Or, if you really need a byte string:
    s = b'Cafe'          # type(s) == <class 'bytes'>
    s = 'Café'.encode()  # type(s) == <class 'bytes'>
    

    Note that you must encode a Python 3 string to convert it into a bytes representation of that string. The default encoding is UTF-8. Use decode to return a string from encoded bytes:

    >>> s.decode()
    'Café'
    

    While the bytes type exists in both Python 2 and 3, the unicode type only exists in Python 2. To use Python 3's implicit Unicode strings in Python 2, add the following to the top of your code file:

    from __future__ import unicode_literals
    

    In order to check whether your variable contains a string in Python 2, write:

    isinstance(s, basestring)
    

    whereas in Python 3 it is simply:

    isinstance(s, str)
    
  • 44

    In Python 3, you can unpack an iterable even without knowing the exact number of items, and even have a variable hold the end of the iterable, as long as you provide a variable that may collect a list of values, this is done by placing an asterisk before the name. For example, unpacking a list:

    >>> first, second, *tail, last = [1, 2, 3, 4, 5]
    >>> print(first)
    1
    >>> print(second)
    2
    >>> print(tail)
    [3, 4]
    >>> print(last)
    5
    

    Note: When using the *variable syntax, the variable will always be a list, even if the original type wasn't a list. It may contain zero or more elements depending on the number of elements in the original list.

    >>> first, second, *tail, last = [1, 2, 3, 4]
    >>> print(tail)
    [3]
    
    >>> first, second, *tail, last = [1, 2, 3]
    >>> print(tail)
    []
    

    Similarly, unpacking a str:

    >>> begin, *tail = "Hello"
    >>> print(begin)
    'H'
    >>> print(tail)
    ['e', 'l', 'l', 'o']
    

    It is also possible to unpack an iterable into function arguments:

    >>> iterable = [1, 2, 3, 4, 5]
    >>> print(iterable)
    [1, 2, 3, 4, 5]
    >>> print(*iterable)
    1 2 3 4 5
    

    It is worth mentioning that, since * eats up a variable number of items in the given sequence, it is not allowed to have two *s for the same expression - it wouldn't know how many elements went into the first unpacking, and how many in the second:

    >>> *head, *tail = [1, 2]
    SyntaxError: two starred expressions in assignment
    

I am downvoting this example because it is...

Syntax

Syntax

Parameters

Parameters

Remarks

There are currently two supported versions of Python: 2.7 (Python 2) and 3.5 (Python 3).

Python 2 is backwards-compatible with most earlier versions of Python, and can run Python code from most 2.y versions of Python unchanged. It is broadly available, with an extensive collection of packages. It is also considered deprecated by the CPython developers, and receives only security and bug-fix development. The CPython developers intend to abandon this version of the language.

Python 3 intentionally broke backwards-compatibility, to address concerns the language developers had with the core of the language. Python 3 receives new development and new features. It is the version of the language that the language developers intend to move forward with.

Over the time between the initial release of Python 3.0 and the current version, some features of Python 3 were back-ported into Python 2, and other parts of Python 3 were extended to have syntax compatible with Python 2. Therefore it is possible to write Python that will work on both Python 2 and Python 3, by using use future imports and special modules (like six).

Future imports have to be at the beginning of your module:

from __future__ import print_function
# other imports and instructions go after __future__
print('Hello world')

For further information on the __future__ module, see the relevant page in the Python documentation.

Still have a Compatibility between Python 3 and Python 2 question? Ask Question

Integer division

85

The standard division symbol / operates differently between Python 2 and Python 3.

Python 3 produces a floating point result even when both operands are integers. Meanwhile, when dividing an integer by another integer, Python 2 rounds the result down to the nearest integer (also known as taking the floor of, or rounding toward negative infinity):

         # Python 2:   Python 3:
3 / 2    #     1          1.5
4 / 2    #     2          2.0
2 / 3    #     0          0.6666666666666666
-3 / 2   #    -2         -1.5

There is also the integer division symbol //, which has the same function in both languages: rounds down to the nearest integer (i.e., works the same as the / symbol from Python 2).

         # Python 2:   Python 3:
3 // 2   #     1           1
-3 // 2  #    -2          -2

The truncating behavior was deprecated in Python 2.2, but still remains in Python 2.7 for the sake of backward compatibility. If you're writing new code in Python 2, you should enable the new division behaviour and make your code Python 3 compatible by adding from __future__ import division:

# needs to be the first statement in a module
from __future__ import division

         # Python 2  Python 3:
3 / 2    #    1.5       1.5
-3 / 2   #   -1.5      -1.5

Note: some other programming languages use rounding toward zero (truncation) rather than rounding down (toward negative infinity) as Python does (i.e. in those languages -3 / 2 == -1). This may create confusion when porting or comparing code.


As an alternative to from __future__ import division, one can use the normal division symbol / but make sure that at least one of the operands is a float: 3 / 2.0 == 1.5. However this is a bad practice, it is just too easy to write average = sum(items) / len(items) and forget to cast one of the arguments to float. Moreover, such cases may frequently evade notice during testing, if you test on an array containing floats, and then in production receive an array of ints. See PEP-238 for detailed rationale why the division operator was changed in Python 3 and why the old-style division should be avoided. Additionally, a code that expects that 3 / 2 == 1 wouldn't work correctly on Python 3.

Byte Strings vs Unicode strings

48

In Python 2 there are two types generally used for text: str and unicode. A non-prefixed string literal would mean a byte string by default. In order to define a Unicode string literal you need to prefix the literal with u prefix:

s = 'Cafe'    # type(s) == <type 'str'>
s = u'Café'   # type(s) == <type 'unicode'>

In Python 2, the type str is commonly used for both text and binary data.

In Python 3, all text is Unicode. To create a binary data literal, you can prefix b to a string literal to define it as a byte string:

s = 'Cafe'           # type(s) == <class 'str'>
s = 'Café'           # type(s) == <class 'str'>
# Or, if you really need a byte string:
s = b'Cafe'          # type(s) == <class 'bytes'>
s = 'Café'.encode()  # type(s) == <class 'bytes'>

Note that you must encode a Python 3 string to convert it into a bytes representation of that string. The default encoding is UTF-8. Use decode to return a string from encoded bytes:

>>> s.decode()
'Café'

While the bytes type exists in both Python 2 and 3, the unicode type only exists in Python 2. To use Python 3's implicit Unicode strings in Python 2, add the following to the top of your code file:

from __future__ import unicode_literals

In order to check whether your variable contains a string in Python 2, write:

isinstance(s, basestring)

whereas in Python 3 it is simply:

isinstance(s, str)

Unpacking Iterables

44

In Python 3, you can unpack an iterable even without knowing the exact number of items, and even have a variable hold the end of the iterable, as long as you provide a variable that may collect a list of values, this is done by placing an asterisk before the name. For example, unpacking a list:

>>> first, second, *tail, last = [1, 2, 3, 4, 5]
>>> print(first)
1
>>> print(second)
2
>>> print(tail)
[3, 4]
>>> print(last)
5

Note: When using the *variable syntax, the variable will always be a list, even if the original type wasn't a list. It may contain zero or more elements depending on the number of elements in the original list.

>>> first, second, *tail, last = [1, 2, 3, 4]
>>> print(tail)
[3]

>>> first, second, *tail, last = [1, 2, 3]
>>> print(tail)
[]

Similarly, unpacking a str:

>>> begin, *tail = "Hello"
>>> print(begin)
'H'
>>> print(tail)
['e', 'l', 'l', 'o']

It is also possible to unpack an iterable into function arguments:

>>> iterable = [1, 2, 3, 4, 5]
>>> print(iterable)
[1, 2, 3, 4, 5]
>>> print(*iterable)
1 2 3 4 5

It is worth mentioning that, since * eats up a variable number of items in the given sequence, it is not allowed to have two *s for the same expression - it wouldn't know how many elements went into the first unpacking, and how many in the second:

>>> *head, *tail = [1, 2]
SyntaxError: two starred expressions in assignment

Print statement vs. Print function

30

In Python 2 print is a statement:

print "Hello World"
print                         # print a newline
print "No newline",           # add trailing comma to remove newline 
print >>sys.stderr, "Error"   # print to stderr

Whilst in Python 3 print() is a function, with keyword arguments for common uses:

print("Hello World")
print()                          # print a newline (must use parentheses)
print("No newline", end="")      # end specifies what to append (defaults to newline)
print("Error", file=sys.stderr)  # file specifies the output buffer
print("Comma", "separated", "output", sep=",")  # sep specifies the separator
print("A", "B", "C", sep="")     # null string for sep: prints as ABC
print("Flush this", flush=True)  # flush the output buffer

Note that in Python 2, even without from __future__ import print_function, you can equivalently use parenthesis (but only around a single argument):

print(1)     # prints 1
print(1, 2)  # prints the tuple (1, 2)

The print function has the following parameters:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

sep is what separates the objects you pass to print. For example:

print('foo', 'bar', sep='~') # out: foo~bar
print('foo', 'bar', sep='.') # out: foo.bar

end is what the end of the print statement is followed by. For example:

print('foo', 'bar', end='!') # out: foo bar!

Printing again following a non-newline ending print statement will print to the same line:

print('foo', end='~')
print('bar')
# out: foo~bar

Note : For future compatibility, print function is also available in Python 2.6 onwards; however it cannot be used unless parsing of the print statement is disabled with

from __future__ import print_function

This function has exactly same format as Python 3's, except that it lacks the flush parameter.

Differences between range and xrange functions

18

In Python 2, range function returns a list while xrange creates a special xrange object (an immutable sequence):

>>> range(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> xrange(1, 10)
xrange(1, 10)

>>> isinstance(xrange(1, 10), xrange)
True

In Python 3, xrange was renamed to range, which thus now creates a range object. There is no xrange type:

>>> range(1, 10)
range(1, 10)

>>> isinstance(range(1, 10), range)
True

>>> xrange(1, 10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined

The advantage of using a special sequence type instead of a list is that the interpreter does not have to allocate memory for a list and populate it:

>>> range(10000000000000000)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError

>>> xrange(100000000000000000)
xrange(100000000000000000)

Since the latter behaviour is generally desired, the former one was removed in Python 3. If you still want to have a list in Python 3, you can simply use the list() constructor on a range object:

>>> list(range(1, 10))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

To maintain compatibility between both Python 2.x and 3.x versions, you can use the builtins module from future external package to achieve both forward-compatible...

# Python 2 and 3: forward-compatible
from builtins import range

for i in range(10**8):
    pass

...or backward-compatible code:

# Python 2 and 3: backward-compatible
from past.builtins import xrange

for i in xrange(10**8):
    pass

Raising and handling Exceptions

7

This is the Python 2 syntax, note the commas , on the raise and except lines:

try:
    raise IOError, "input/output error"
except IOError, exc:
    print exc

In Python 3, the , syntax is dropped and replaced by parenthesis and the as keyword:

try:
    raise IOError("input/output error")
except IOError as exc:
    print(exc)

For backwards compatibility, the Python 3 syntax is also available in Python 2.6 onwards, so it should be used for all new code that does not need to be compatible with previous versions.


Python 3 also adds exception chaining, wherein you can signal that some other exception was the cause for this exception. For example

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from e

The exception raised in the except statement is of type DatabaseError, but the original exception is marked as the __cause__ attribute of that exception. When the traceback is displayed, the original exception will also be displayed in the traceback:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

If you throw in an except block without explicit chaining:

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}')

The traceback in Python 3 is

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

Neither one is supported in Python 2. To "forget" the previously thrown exception, use raise from None

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from None

Now the traceback would simply be

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

Comparison of different types

6
Python 2.x2.3

Objects of different types can be compared. The results are arbitrary, but consistent. They are ordered lexicographically by type so an 'int' is less than a 'string' and a 'tuple' is greater than a 'list':

[1, 2] > 'foo'
# Out: False
(1, 2) > 'foo'
# Out: True
[1, 2] > (1, 2)
# Out: False
100 < [1, 'a'] < 'abc' < (1, 'a')
# Out: True

This was originally done so a list of mixed types could be sorted and objects would be grouped together by type:

l = [7, 'a', (1,2), [5,6], 5, 8.0, 'b', 1.2, [7, 8], 'c']
sorted(l)
# Out: [1.2, 5, 7, 8.0, [5, 6], [7, 8], 'a', 'b', 'c', (1, 2)]
Python 3.x3.0

An exception is raised when comparing different (non-numeric) types:

1 < 1.5
# Out: True
[1, 2] > 'foo'
TypeError: unorderable types: list() > str()
(1, 2) > 'foo'
TypeError: unorderable types: tuple() > str()
[1, 2] > (1, 2)
TypeError: unorderable types: list() > tuple()

Leaked variables in list comprehension

5

Python 2.x

>>> x = 'hello world!'
>>> vowels = [x for x in 'AEIOU']
>>> x
'U'

Python 3.x

>>> x = 'hello world!'
>>> vowels = [x for x in 'AEIOU']
>>> x
'hello world!'

As can be seen from the example, the local variable from the list comprehension does not mask variables from the surrounding scope.

Additionally, neither generator expressions available in Python since 2.5 nor dictionary or set comprehensions, which were backported to Python 2.7 from Python 3, leak variables in Python 2.

Note that both Python 2 and Python 3 will leak the into the surrounding scope when using a for-loop:

>>> x = 'hello world!'
>>> vowels = []
>>> for x in 'AEIOU':
...  vowels.append(x)
...
>>> x
'U'

Removed operator <>, alternate repr syntax, L suffix for longs, ur'' strings

5

In Python 2 <> is a synonym for !=; likewise `foo` was a synonym for repr(foo). In Python 2 long integer literals first to be suffixed with L or l, which later became optional. L or l suffixes are not supported in Python 3. Finally, though Python 3 supports both raw strings and optional u prefix since version 3.3, ur prefix (for "raw unicode strings") is not supported.

Python 2:

>>> 1 <> 2
True
>>> 1 <> 1
False
>>> foo = 'hello world'
>>> repr(foo)
"'hello world'"
>>> `foo`
"'hello world'"
>>> 1L
1L
>>> type(1L)
<type 'long'>
>>> ur'raw string\n'
u'raw string\\n'

However in Python 3:

>>> 1 <> 2
  File "<stdin>", line 1
    1 <> 2
       ^
SyntaxError: invalid syntax
>>> `foo`
      File "<stdin>", line 1
    `foo`
    ^
SyntaxError: invalid syntax

>>> 1L
  File "<stdin>", line 1
    1L
     ^
SyntaxError: invalid syntax

>>> r'raw string\n'
'raw string\\n'
>>> ur'raw string\n'
  File "<stdin>", line 1
    ur'raw string\n'
                   ^
SyntaxError: invalid syntax

yield from

5

Since Python 3.3 it is possible to delegate generation:

def countdown(n):
    if n >= 0:
        yield n
        yield from countdown(n-1)

for number in countdown(5):
    print(number) # 5 4 3 2 1 0

For basic iterators, countdown could be implemented roughly equivalently as:

def countdown(n):
    if n >= 0:
        yield n
        for number in countdown(n-1):
            yield number

However, yield from will also propagate up values received by send and the yield from expression evaluates to the return value of the delegated function.

def inner():
    x = yield "inner yield"
    yield "received value: " + x
    return "inner return"

def outer():
    inner_ret = yield from inner()
    yield "first outer yield + " + inner_ret
    return "outer return"

example = outer()

next(example)
#>>> 'inner yield'

example.send("sent value")
#>>> 'received value: sent value'

next(example)
#>>> 'first outer yield + inner return'

next(example)
#>>> Traceback (most recent call last):
#>>>   File "", line 22, in <module>
#>>> StopIteration: outer return

All classes are "new-style classes" in Python 3.

4

In Python 3.x all classes are new-style classes; when defining a new class python implicitly makes it inherit from object. As such, specifying object in a class definition is a completely optional:

class A: pass
class B(object): pass

Both of these classes now contain object in their mro (method resolution order):

>>> A.__mro__
(__main__.A, object)

>>> B.__mro__
(__main__.B, object)

In Python 2.x classes are, by default, old-style classes; they do not implicitly inherit from object. This causes the semantics of classes to differ depending on if we explicitly add object as a base class:

class A: pass
class B(object): pass

In this case, if we try to print the __mro__ of B, similar output as that in the Python 3.x case will appear:

>>> B.__mro__
(<class '__main__.B'>, <type 'object'>)

This happens because we explicitly made B inherit from object when defining it: class B(object): pass. For class A which does not inherit from object the __mro__ attribute does not exist, trying to access it results in an AttributeError.

In order to ensure compatibility between both versions of Python, classes can be defined with object as a base class:

class mycls(object):
    """ I am fully compatible with Python 2/3"""

The next() method does not exist in Python 3, use next() function

4

In Python 2, an iterable can be traversed by using a method called next on the iterable itself:

g = (i for i in range(0,3))
g.next()  # Yields 0
g.next()  # Yields 1
g.next()  # Yields 2

In Python 3 calling .next will raise an AttributeError:

gen = (x for x in "123")
print(next(gen))  # Prints 1
print(gen.next())  # AttributeError: 'generator' object has no attribute 'next'

The iterable protocol in 3.x instead relies on a method called __next__, which is accessed by the built-in function called next:

g = (i for i in range(0,3))
next(g)  # Yields 0
next(g)  # Yields 1
next(g)  # Yields 2

The next built-in function also exists from Python 2.6, making the above example work in both Python 2 and Python 3.

dict methods

3

Changing in the return value

In Python 3 the dict.items method now returns a view object while in Python 2 it returns a list, which could potentially use up a lot of memory if the dictionary to be copied is very large. The equivalent of dict.items in python2 is dict.iteritems.

dict.iteritems doesn't exist in Python 3, since dict.items already returns an iterator.

Python 2

>>> a = {1: 'one', 2: 'two', 3: 'three'}
>>> a
{1: 'one', 2: 'two', 3: 'three'}
>>> a.items()
[(1, 'one'), (2, 'two'), (3, 'three')]
>>> a.iteritems()
<dictionary-itemiterator object at 0x7fb5573dd520>
>>> [i for i in a.iteritems()]
[(1, 'one'), (2, 'two'), (3, 'three')]

Python 3

>>> a = {1: 'one', 2: 'two', 3: 'three'}
>>> a
{1: 'one', 2: 'two', 3: 'three'}
>>> a.items
<built-in method items of dict object at 0x7f9f3d54c308>
>>> a.items()
dict_items([(1, 'one'), (2, 'two'), (3, 'three')])
>>> [i for i in a.items()]
[(1, 'one'), (2, 'two'), (3, 'three')]

The same also goes for other dictionary methods: dict.keys, dict.values and dict.items return a list in Python 2, whilst in Python 3 they return a view object.

dict.viewkeys, dict.viewvalues and dict.viewitems have been back-ported to Python 2.7 to return view objects when they're called; however, these methods are not valid in Python 3.

Method .has_key() of Python2x

In Python 2 dict.has_key() is used to test whether the dict has a certain key.

>>> a = {1: 'one', 2: 'two', 3: 'three'}
>>> a.has_key(1)
True

But this method has been removed in Python 3. Instead, the in operator Is used.

>>> a = {1: 'one', 2: 'two', 3: 'three'}
>>> a.has_key(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'has_key'
>>> 1 in a
True

Renamed modules

3

A few modules in the standard library have been renamed:

Old nameNew name
_winregwinreg
ConfigParserconfigparser
copy_regcopyreg
Queuequeue
SocketServersocketserver
_markupbasemarkupbase
reprreprlib
test.test_supporttest.support
Tkintertkinter

Compatibility

When mantaining compatibility between both Python 2.x and 3.x versions, you can use the future external package to enable importing top-level standard library packages with Python 3.x names on Python 2.x versions.

Branching based on Python version

2

If you need to execute different code for different Python versions, then do consider that in time be a Python 4 with which your code could be compatible. Thus, for version tests, test whether the current version is Python 2, or greater than Python 2. It is common to define two variables PY2 and PY3 where PY2 is true for Pythons 2 (and 1 and 0.x), and PY3 for versions 3.0 and up:

import sys
PY2 = sys.version_info < (3,)
PY3 = not PY2

Some guides advocate the way PY3 = sys.version_info[0] == 3, but it will break whenever Python 4 is released.

Then you can use for example

if PY2:
    text_type = unicode
else:
    text_type = str

You shouldn't branch everywhere but instead refactor your code so that a whole function definition is changed based on whether 2 or 3 is in use. Thus do not write

def my_func():
    if PY2:
        # Python 2 way
    else:
        # Python 3 way

but rather

if PY2:
    def my_func():
        # Python 2 way
else:
    def my_func():
        # Python 3 way

Exception Handling

2

In Python 2, you may have seen

try:
    ...
except ValueError, e:
    ...

To ensure compatibility, prefer

try:
    ...
except ValueError as e:
    ...

To catch multiple types of exceptions, use a tuple of classes:

try:
    ...
except (ValueError, TypeError) as e:
    ...

PEP 3113: Removed untupling syntax for functions

2

In python 2 one could hierarchically organize arguments:

def foo(a,  (b, c)):
    print a, b, c

foo(1, [2, 3]) # outputs 1, 2, 3

However in python 3 this syntax is not supported for functions and lambdas. Equivalent code for python 3 is:

def foo(a,  b_c):
    b, c = b_c
    print(a, b, c)

use __future__ imports

2

Your code should use the following __future__ imports at the top of your module:

from __future__ import print_function, division, absolute_import

These will make the print function as opposed to print statement available within the module, make the / operator perform a true division instead of flooring division and make the import statement work like in Python 3.

There is one additional __future__ import, unicode_literals, which makes 'string' literals generate unicode strings in Python 3. However, this can lead to problems, as there are some functions that expect str in Python 2 and str in Python 3. Additionally, since Python 3.3, optional u prefix is allowed for strings.

Thus, if you don't use unicode_literals, you can use:

# a bytes binary data literal; actually `str` in Python 2, `bytes` in Python 3
b'123'

# a `str` literal; the type named `str` in both Pythons
'123'

# a unicode literal; this is of type `unicode` in Python 2, and type `str` in Python 3
u'123'

User Input

2

In Python 2, user input is accepted using the raw_input function,

user_input = raw_input()

While in Python 3 user input is accepted using the input function.

user_input = input()

In Python 2, the input function will accept input and interpret it. While this can be useful, it has several security considerations and was removed in Python 3. To access the same functionality, eval(input()) can be used.

Absolute/Relative Imports

1

In Python 3, PEP 404 changes the way imports work from Python 2. Implicit relative imports are no longer allowed in packages and from ... import * imports are only allowed in module level code.

To achieve Python 3 behavior in Python 2:

  • the absolute imports feature can be enabled with from __future__ import absolute_import
  • explicit relative imports are encouraged in place of implicit relative imports

For clarification, in Python 2, a module can import the contents of another module located in the same directory as follows:

import foo

Notice the location of foo is ambiguous from the import statement alone. This type of implicit relative import is thus discouraged in favor of explicit relative imports, which look like the following:

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

The dot . allows an explicit declaration of the module location within the directory tree.

Compatible Subclassing with super

1

Given a class

class Pet(object):
    """A parent class."""
    def __init__(self, name):
        self.name = name

super() - Python 2/3 Compatible

Python 2 and 3 support a concise way to subclass using super().

class Python(Pet):
    "A sub-class using super() with args."
    def __init__(self, name):
        super(Python, self).__init__(name)                 # py2/3 compatible
        
python = Python("Monty")
python.name

# Py2/3 Output: 'Monty'

New super() - Python 3-only

Note that arguments in super() are listed in reverse and is related to Python's Method Resoultion Order (MRO). I has been a source of much confusion among users. Therefore, since Python 3, super() was modified and no longer requires arguments as revised in PEP 3135.

class Python(Pet):
    "A sub-class using super() without args."
    def __init__(self, name):
        super().__init__(name)                             # no args; only py3 compatible
        
python = Python("Monty")
python.name

# Py2 Output: TypeError: super() takes at least 1 argument (0 given)
# Py3 Output: 'Monty'

Be aware that using this new super() (without arguments) is incompatible with Python 2. For more insight, see the rationale behind the new super() explained by Python Core Developer, Raymond Hettinger.

Dictionary method changes

1

In Python 3, many of the dictionary methods are quite different in behaviour from Python 2, and many were removed as well: has_key, iter* and view* are gone. Instead of d.has_key(key), which had been long deprecated, one must now use key in d.

In Python 2, dictionary methods keys, values and items return lists. In Python 3 they return view objects instead; the view objects are not iterators, and they differ from them in two ways, namely:

  • they have size (one can use the len function on them)
  • they can be iterated over many times

Additionally, like with iterators, the changes in the dictionary are reflected in the view objects.

Python 2.7 has backported these methods from Python 3; they're available as viewkeys, viewvalues and viewitems. To transform Python 2 code to Python 3 code, the corresponding forms are:

  • d.keys(), d.values() and d.items() of Python 2 should be changed to list(d.keys()), list(d.values()) and list(d.items())
  • d.iterkeys(), d.itervalues() and d.iteritems() should be changed to iter(d.iterkeys()), or even better, iter(d); iter(d.values()) and iter(d.items()) respectively
  • and finally Python 2.7 method calls d.viewkeys(), d.viewvalues() and d.viewitems() can be replaced with d.keys(), d.values() and d.items().

Porting Python 2 code that iterates over dictionary keys, values or items while mutating it is sometimes tricky. Consider:

d = {'a': 0, 'b': 1, 'c': 2, '!': 3}
for key in d.keys():
    if key.isalpha():
        del d[key]

The code looks as if it would work similarly in Python 3, but there the keys method returns a view object, not a list, and if the dictionary changes size while being iterated over, the Python 3 code will crash with RuntimeError: dictionary changed size during iteration. The solution is of course to properly write for key in list(d.keys()).

Similarly, view objects behave differently from iterators: one cannot use next() on them, and one cannot resume iteration; it would instead restart; if Python 2 code passes the return value of d.iterkeys(), d.itervalues() or d.iteritems() to a method that expects an iterator instead of an iterable, then that should be iter(d.keys()), iter(d.values()) or iter(d.items()) in Python 3.

Differences in filter, map and zip

1

In Python 2 filter, map and zip builtins return a sequence:

>>> s = filter(None, [0, 1, 2])
>>> s
[1, 2]
>>> s = map(lambda x: x * x, [0, 1, 2])
>>> s
[0, 1, 4]
>>> s = zip([0, 1, 2], [3, 4, 5])
>>> s
[(0, 3), (1, 4), (2, 5)]

In Python 3 filter, map and zip return iterator instead:

>>> it = filter(None, [0, 1, 2])
>>> it
<filter object at 0x000000E0763C2CC0>
>>> list(it)
[1, 2]
>>> it = map(lambda x: x * x, [0, 1, 2])
>>> it
<map object at 0x000000E0763C2D30>
>>> list(it)
[0, 1, 4]
>>> it = zip([0, 1, 2], [3, 4, 5])
>>> it
<zip object at 0x000000E0763C52C8>
>>> list(it)
[(0, 3), (1, 4), (2, 5)]

Since Python 3 zip is equivalent of Python 2 itertools.izip it has been removed in Python 3.

Extended List, Set, and Dictionary Unpacking

1

Python 3.5+ supports extended unpacking.

List

>>> [-1, *range(4), -2]
[-1, 0, 1, 2, 3, -2]

Set

>>> {-1, *range(4), -2, *range(-4, -6, -1)}
{0, 1, 2, 3, -2, -5, -4, -1}

Dictionary

>>> a = {1: "one", 2: "two"}
>>> b = {3: "three", 2: "other-two"}
>>> {5: 'five', **a}
{1: 'one', 2: 'two', 5: 'five'}

Later values override earlier ones:

>>> {1: 'foo', 5: 'five', **a, **b}
{1: 'one', 2: 'other-two', 3: 'three', 5: 'five'}

Function parameter unpacking

1

Python 2:

def intervals_overlap((left1, right1), (left2, right2)):
    return max(left1, left2) < min(right1, right2)

In Python 3, you'll have to do it explicitly in the function body:

def intervals_overlap(interval1, interval2):
    left1, right1 = interval1
    left2, right2 = interval2
    return max(left1, left2) < min(right1, right2)

Octal Constants

1

In Python 2, an octal literal could be defined as

0755

To ensure cross-compatibility, use

0o755

Package six for Python 2/3 compatibility

1

The package six provide utilities for Python 2/3 compatibility:

  • unified access to renamed libraries
  • variables for string/unicode types
  • functions for method that got removed or has been renamed

Reduce is no longer a built-in

1

In Python 2, reduce is available either as a built-in function or from the functools package (version 2.6 onwards), whereas in Python 3 reduce is available only from functools. However the syntax for reduce in both Python2 and Python3 is the same and is reduce(function_to_reduce, list_to_reduce).

As an example, let us consider reducing a list to a single value by dividing each of the adjacent numbers. Here we use divmod function from the operator library.

In Python 2.x it is as simple as:

>>> my_list = [1,2,3,4,5]
>>> import operator
>>> reduce(operator.truediv,my_list)
0.008333333333333333

In Python 3.x the example becomes a bit more complicated:

>>> my_list = [1,2,3,4,5]
>>> import operator, functools
>>> functools.reduce(operator.truediv,my_list)
0.008333333333333333

We can also use from functools import reduce to avoid calling reduce with the namespace name.

The nonlocal statement

1

Python 3 introduced the nonlocal statement. In python 2, this would be wrong:

def add(x, y):
    result = 0
    def addhelper(x,y):
        result = x+y
    addhelper(x, y)
    return result

as it would simply return 0. However, in Python 3, you can do this:

...
def addhelper(x, y):
    nonlocal result  # This shows the variable scope result is in
    result = x+y
...

as the nonlocal statement shows the variable scope of result.

The nonlocal statement is especially useful in decorators, where there are nested function definitions.

unicode_literals

1

Python3 treats every string literal as unicode. Generally, in Python2 you need to add a u prefix (u"string"). This import (available since Python 2.6) makes this behavior consistent:

>>> from __future__ import unicode_literals
>>> "hi"
u'hi'
>>>

Accessing dictionary key value pairs

0

Python 2

In Python 2, there are two methods for accessing the key value pairs in a dictionary.

pets = {'dogs': 6, 'cats': 3, 'parakeets': 22}

pets.items()  # [('cats', 3), ('dogs', 6), ('parakeets', 22)]
pets.iteritems()  # <dictionary-itemiterator object at 0x1005e8100>

The difference between these two is that items() returns a list of tuples where each tuple represents a key value pair in the dictionary whereas iteritems() returns an iterator over the key value pairs in the dictionary. Often, iteritems() is preferable because it is a generator whereas items() keeps all the pairs in memory.

Python 3

In Python 3, it was decided that the behavior of iteritems() was a preferred to that of items() so items() returns an iterator like Python 2's iteritems() and iteritems() was removed in Python.

pets = {'dogs': 6, 'cats': 3, 'parakeets': 22}

pets.items()  # dict_items([('parakeets', 22), ('cats', 3), ('dogs', 6)])
pets.iteritems()  # AttributeError: 'dict' object has no attribute 'iteritems'

As seen above, a items() in Python 3 returns a dict_items object, which is called a "view object".

From the Python documentation:

[view objects] provide a dynamic view on the dictionary’s entries, which means that when the dictionary changes, the view reflects these changes.

For example:

items = pets.items()  # items == dict_items([('parakeets', 22), ('cats', 3), ('dogs', 6)])
pets['hamsters'] = 10  # items == dict_items([('parakeets', 22), ('cats', 3), ('hamsters', 10), ('dogs', 6)])

To replicate behavior of Python 2's items(), call list() on the dict_items object.

list(items)  # [('parakeets', 22), ('cats', 3), ('hamsters', 10), ('dogs', 6)]

cmp function removed in Python 3

0

In Python 3 the cmp built-in function was removed, together with the __cmp__ special method.

From the documentation:

The cmp() function should be treated as gone, and the __cmp__() special method is no longer supported. Use __lt__() for sorting, __eq__() with __hash__(), and other rich comparisons as needed. (If you really need the cmp() functionality, you could use the expression (a > b) - (a < b) as the equivalent for cmp(a, b).)

Moreover all built-in functions that accepted the cmp parameter now only accept the key keyword only parameter.

In the functools module there is also useful function cmp_to_key(func) that allows you to convert from a cmp-style function to a key-style function:

Transform an old-style comparison function to a key function. Used with tools that accept key functions (such as sorted(), min(), max(), heapq.nlargest(), heapq.nsmallest(), itertools.groupby()). This function is primarily used as a transition tool for programs being converted from Python 2 which supported the use of comparison functions.

Division

0
# Available in both Python 2 and 3
# Will make Python 2 divisions behave like in Python 3
from __future__ import division

print(1 / 3) # 0.333333333333
print(1.0 / 3) # 0.333333333333
print(1 // 3) # 0
print(1.0 // 3) # 0.0

encode/decode to hex no longer available

0

Python2:

>>> "1deadbeef3".decode('hex')
'\x1d\xea\xdb\xee\xf3'
>>> '\x1d\xea\xdb\xee\xf3'.encode('hex')
1deadbeef3

Python3:

>>> "1deadbeef3".decode('hex')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'decode'
>>> b"1deadbeef3".decode('hex')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
LookupError: 'hex' is not a text encoding; use codecs.decode() to handle arbitrary codecs
>>> '\x1d\xea\xdb\xee\xf3'.encode('hex')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs
>>> b'\x1d\xea\xdb\xee\xf3'.encode('hex')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'bytes' object has no attribute 'encode'

However, as suggested by the error message, you can use the codecs module to achieve the same result:

>>> codecs.decode('1deadbeef4', 'hex')
b'\x1d\xea\xdb\xee\xf4'
>>> codecs.encode(b'\x1d\xea\xdb\xee\xf4', 'hex')
b'1deadbeef4'

Note that codecs.encode returns a bytes object. To obtain a str object just decode to ASCII:

>>> codecs.encode(b'\x1d\xea\xdb\xee\xff', 'hex').decode('ascii')
'1deadbeeff'

Exception chaining

0

Exception chaining introduced in Python 3.0 with PEP 3134.

In Python 2.x original exception and its traceback will be lost if new exception will be raised in except block. Following code can be used for compatibility:

import sys
import traceback

try:
    funcWithError()
except:
    sys_vers = getattr(sys, 'version_info', (0,))
    if sys_vers < (3,0):
        traceback.print_exc()
    raise Exception("new exception")

exec statement is a function in Python 3

0

In Python 2, exec is a statement, with special syntax: exec code [in globals[, locals]]. In Python 3 exec is now a function: exec(code, [, globals[, locals]]), and the Python 2 syntax will raise a SyntaxError.

As print was changed from statement into a function, a __future__ import was also added. However, there is no from __future__ import exec_function, as it is not needed: the exec statement in Python 2 can be also used with syntax that looks exactly like the exec function invocation in Python 3. Thus you can change the statements

exec 'code'
exec 'code' in global_vars
exec 'code' in global_vars, local_vars

to forms

exec('code')
exec('code', global_vars)
exec('code', global_vars, local_vars)

and the latter forms are guaranteed to work identically in both Python 2 and Python 3.

File I/O

0

file is no longer a builtin name in 3.x (open still works).

Internal details of file I/O have been moved to the standard library io module, which is also the new home of StringIO:

import io
assert io.open is open # the builtin is an alias
buffer = io.StringIO()
buffer.write('hello, ') # returns number of characters written
buffer.write('world!\n')
buffer.getvalue() # 'hello, world!\n'

The file mode (text vs binary) now determines the type of data produced by reading a file (and type required for writing):

with open('data.txt') as f:
    first_line = next(f)
    assert type(first_line) is str
with open('data.bin', 'rb') as f:
    first_kb = f.read(1024)
    assert type(first_kb) is bytes

The encoding for text files defaults to whatever is returned by locale.getpreferredencoding(False). To specify an encoding explicitly, use the encoding keyword parameter:

with open('old_japanese_poetry.txt', 'shift_jis') as text:
    haiku = text.read()

generator_stop

0
Python 3.x3.5
from __future__ import generator_stop

Changes a StopIteration exception in a generator into a RuntimeError.

Get web page content

0
try:
    # For Python 3.0 and later
    from urllib.request import urlopen
except ImportError:
    # Fall back to Python 2's urllib2
    from urllib2 import urlopen

url = 'https://en.wikipedia.org/wiki/Python_(programming_language)'
response = urlopen(url)
data = str(response.read())

How do I check whether a variable is an integer (of any kind)?

0

You can do this :

# Python 2 and 3: 
import sys
if sys.version_info < (3,):
    integer_types = (int, long,)
else:
    integer_types = (int,)

>>> isinstance(1, integer_types)
True

# Python 2 only:
if isinstance(x, (int, long)):
     ...

# Python 3 only:
if isinstance(x, int):
    ...

source: http://python3porting.com/differences.html

Inheriting from object

0

Classes in Python 2 can belong to one of two flavors: old-style and new-style. The issue arises from the fact that in Python 3 object is implicitly added as a base class so:

class Foo: pass

and

class Foo(object): pass

have the same semantics regarding inheritance.

In order to be compatible with both versions of Python one must be aware to explicitly add object as a base class in Python 3:

class Foo(object):
    pass

If by any change one omits the inclusion of object in the base classes and runs his/her code in Python 2 an 'old-style' class is going to be created and follow differing semantics than those expected.

Keyword only arguments

0

In Python 3 you can define a function that takes non-defaulted/keyword-only arguments.

>>> def foo(bar, *, baz):
...     return bar, baz

Arguments following the star * behave as keyword arguments. Calling foo() with the baz argument passed by keyword works

>>> foo(1, baz=2)
(1, 2)

whilst using just positional arguments raises a TypeError

>>> foo(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes 1 positional argument but 2 were given

The bare * is just syntax to differentiate positional and keyword arguments, and does not imply the function takes variadic arguments. However, variadic arguments and keyword-only arguments can be easily combined:

>>> def foo(*args, baz):
...     return args, baz
...
>>> foo(1, 2, 3, baz=4)
((1, 2, 3), 4)

map()

0

In Python 2 map returns a list

In Python 3 map returns a map object.

# Python 2.X

>>> map(str, [1, 2, 3, 4, 5])
['1', '2', '3', '4', '5']
>>> type(_)
>>> <class 'list'>

# Python 3.X

>>> map(str, [1, 2, 3, 4, 5])
<map object at 0x*>
>>> type(_)
<class 'map'>

# We need to apply map again because we "consumed" the previous map....

>>> map(str, [1, 2, 3, 4, 5])
>>> list(_)
['1', '2', '3', '4', '5')

In Python 2, you can pass None to serve as an identity function. This no longer works in Python 3.

In Python2:

>>> map(None, [0, 1, 2, 3, 0, 4])
[0, 1, 2, 3, 0, 4]

In Python 3:

>>> list(map(None, [0, 1, 2, 3, 0, 5]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

Moreover, when passing more than one iterable as argument in Python 2, map pads the shorter iterables with Nones (similar to itertools.izip_longest). In Python 3, iteration stops after the shorter iterable.

In Python 2:

>>> map(None, [1, 2, 3], [1, 2, 3, 4, 5])
[(1, 1), (2, 2), (3, 3), (None, 4), (None, 5)]

In Python 3:

>>> list(map(lambda x, y: (x, y), [1,2,3], [1,2,3,4,5]))
[(1, 1), (2, 2), (3, 3)]

Note: consider using list comprehensions instead of map, which are Python 2/3 compatible. Replacing the first:

>>> [str(i) for i in [1, 2, 3, 4, 5]]
['1', '2', '3', '4', '5']

round() tie-breaking

0

In Python 2, using round() on a number equally close to two integers will return the one furthest from 0. For example:

round(1.5)  # Out: 2.0
round(0.5)  # Out: 1.0
round(-0.5)  # Out: -1.0
round(-1.5)  # Out: -2.0

In Python 3 however, round() will return the even integer (aka bankers' rounding). For example:

round(1.5)  # Out: 2
round(0.5)  # Out: 0
round(-0.5)  # Out: 0
round(-1.5)  # Out: -2

The round() function return type

0

The round() function returns a float type in Python 2.7

>>> round(4.8)
5.0

Starting in Python 3.5, if the ndigits argument is omitted, it returns an int.

>>> round(4.8)
5

urlparse to urllib.parse

0

Python2

import urlparse

Python3

import urllib.parse

For converting to Python3 from Python2, you can use one of the two techniques:

try/except block:

try:
    import urlparse
except ImportError:
    import urllib.parse as urlparse

check python version explictly

import sys

if sys.version_info.major == 2:
    import urlparse
else:
    import urllib.parse as urlparse

Topic Outline