![]() |
VOOZH | about |
This appendix contains a listing of the differences between Python 2 and Python 3 and example code that will run both in Python 2 and Python 3 without conversion.
This listing is incomplete. What is listed here is only the intentional changes that are not bug fixes and even so there may be accidental omissions.
2to3 fixer ☑ six support ☐
The Python 2 builtin has been removed in Python 3. It’s used to call a function, but since you can call the function directly it serves no purpose and has been deprecated since Python 2.3. There is no replacement.
2to3 fixer ☑ six support ☐
The Python 2 builtin is replaced by the class in Python 3. They are not fully compatible, so does not change this unless you explicitly specify the fixer.
This code will run in both Python 2 and Python 3 without conversion:
>>> import sys >>> if sys.version_info > (3,): ... buffer = memoryview >>> b = buffer('yay!'.encode()) >>> len(b) 4
2to3 fixer ☑ six support ☑
The Python 2 builtin was removed in Python 3.0, but reintroduced in Python 3.2. If you need to support Python 3.1 you can try to call the object under scrutiny and catch the if it is not callable.
If you need to know if something is callable without calling it, there are several solutions for Python 3:
>>> def afunction(): ... pass >>> any("__call__" in klass.__dict__ for ... klass in type(afunction).__mro__) True >>> import collections >>> isinstance(afunction, collections.Callable) True
If you need code that runs in both Python 2 and Python 3 without conversion, you can use this:
>>> hasattr(bool, '__call__') True
The module also defines a function for use under Python 3.
2to3 fixer ☐ six support ☐
In Python 2 there is two types of classes, “old-style” and “new”. The “old-style” classes have been removed in Python 3.
See also Use new-style classes
2to3 fixer ☐ six support ☐
The Python 2 builtin has been removed in Python 3.0.1, although it remained in Python 3.0 by mistake. It is mostly used when defining the comparison method or functions to pass as parameters to and the support for this has been removed in Python 3 as well.
Should you need you can define it like this:
def cmp(a, b): return (a > b) - (a < b)
See Unorderable types, __cmp__ and cmp for more information.
2to3 fixer ☐ six support ☐
The builtin function and the support for the method has been removed in Python 3. would convert the numeric arguments to have the same type according to the coercion rules for Pythons arithmetic operators and was only useful in early versions of Python when implementing new numeric types. There is no replacement in Python 3; coercion should instead be done by the numeric operator methods.
2to3 fixer ☑ six support ☐
In Python 2 dictionaries have the methods , and that return iterators instead of lists. In Python 3 the standard , and return dictionary views, which are iterators, so the iterator variants become pointless and are removed.
If you need to support both Python 2 and Python 3 without conversion and you must use the iterator methods, you can access it via a :
>>> d = {'key1': 'value1', ... 'key2': 'value2', ... 'key3': 'value3', ... } >>> try: ... values = d.itervalues() ... except AttributeError: ... values = d.values() >>> isinstance(values, list) False >>> for value in values: ... print(value) value3 value2 value1
Also, the method on dictionaries is gone. Use the operator instead.
2to3 fixer ☑ six support ☐
In Python 2 the syntax to catch exceptions have changed from:
except (Exception1, Exception2), target:
to the clearer Python 3 syntax:
except (Exception1, Exception2) as target:
Other differences is that the target no longer can be a tuple and that string exceptions are gone. will convert all this, except string exceptions.
Both syntaxes work in Python 2.6 and Python 2.7, but if you need code that is to run in earlier versions as well as Python 3 without conversion you can get the exception object through :
>>> import sys >>> try: ... raise Exception("Something happened") ... except Exception: ... e = sys.exc_info()[1] ... print(e.args[0]) Something happened
2to3 fixer ☑ six support ☐
In Python 2 the exception object is iterable and indexable:
>>> e = Exception('arg1', 'arg2') >>> e[1] 'arg2' >>> for a in e: ... print a ... arg1 arg2
In Python 3 you must use the attribute, which will work under Python 2 as well.
>>> e = Exception('arg1', 'arg2') >>> e.args[1] 'arg2' >>> for a in e.args: ... print a ... arg1 arg2
There was also a attribute on exceptions introduced in Python 2.5, but it was deprecated already in Python 2.6, so it’s unlikely that you will use it.
2to3 fixer ☑ six support ☑
In Python 2 is a statement:
>>> g_dict={} >>> l_dict={} >>> exec "v = 3" in g_dict, l_dict >>> l_dict['v'] 3
In Python 3 is a function:
>>> g_dict={} >>> l_dict={} >>> exec("v = 3", g_dict, l_dict) >>> l_dict['v'] 3
The Python 3 syntax without the global and local dictionaries will work in Python 2 as well:
>>> exec("v = 3") >>> v 3
If you need to pass in the global or local dictionaries you will need to define a custom function with two different implementations, one for Python 2 and one for Python 3. As usual includes an excellent implementation of this called .
2to3 fixer ☑ six support ☐
The Python 2 statement is gone on Python 3. As a replacement you can open the file and read the contents:
exec(open(thefile).read())
This works in all versions of Python.
2to3 fixer ☐ six support ☐
In Python 2 there is a type builtin. This is replaced with various file types in Python 3. You commonly see code in Python 2 that uses which will fail in Python 3. Replace this usage with .
If you need to test for types you can in Python 3 check for instead of .
2to3 fixer ☑ six support ☐
In Python 2 returns a list while in Python 3 it returns an iterator. will in some cases place a call around the call to to ensure that the result is still a list. If you need code that runs in both Python 2 and Python 3 without conversion and you need the result to be a list, you can do the same.
2to3 fixer ☑ six support ☐
In Python 2, if you have a package called and that contains a module called , it would hide the module from the standard library. The code would within import the local file, and importing from the standard library would become tricky.
In Python 3, this has changed so that would import from the standard library, and to import the local file you need to write and needs to be changed to . These are called “relative imports”, and there is also a syntax to import from one level up module above; .
If you need to support both Python 2 and Python 3 without the and syntax has been available since Python 2.5, together with a statement that changes the behavior to the Python 3 behavior.
If you need to support Python 2.4 or earlier you have to spell out the whole package name so becomes and becomes . For clarity and readability I would avoid relative imports if you can and always spell out the whole path.
will check if your imports are local and change them.
2to3 fixer ☐ six support ☐
In Python 2 a tab will be equal to eight spaces as indentation, so you can indent one line with a tab, and the next line with eight spaces. This is confusing if you are using an editor that expands tabs to another number than eight spaces.
In Python 3 a tab is only equal to another tab. This means that each indentation level has to be consistent in its use of tabs and spaces. If you have a file where an indented block sometimes uses spaces and sometimes tabs, you will get the error .
The solution is of course to remove the inconsistency.
2to3 fixer ☑ six support ☐
In Python 2 there is that takes a string from and that takes a string from and evaluates it. That last function is not very useful and has been removed in Python 3, while has been renamed to .
If you need to evaluate the input string you can use :
>>> eval(input('Type in an expression: ')) 'Type in an expression: ' 1+2 3
If you need code that runs in both Python 2 and Python 3 without conversion you can conditionally set to be :
>>> try: ... input = raw_input ... except NameError: ... pass >>> input('Type in a string: ') Type in a string: It works! 'It works!'
2to3 fixer ☐ six support ☐
In Python 2, the result of dividing two integers will itself be an integer; in other words returns . In Python 3 integer division will always return a float. So will return and will return .
If you want the old behavior you should instead use the floor division operator , available since Python 2.2. If you need to support both Python 2 and Python 3 without conversion the following import works since Python 2.2 and enables the new behavior:
>>> from __future__ import division >>> 1/2 0.5
2to3 fixer ☐ six support ☑ (partial)
Python 2 has two integer types and . These have been unified in Python 3, so there is now only one type, . This means that the following code fails in Python 3:
>>> 1L 1L >>> long(1) 1L
It’s quite unusual that you would need to specify that an integer should be a long in Python 2, as Python’s integer functions all will return when needed. If you do require it the following code works on both Python 2 and Python 3 without conversion:
>>> import sys >>> if sys.version_info > (3,): ... long = int >>> long(1) 1L
However, the representation is still different, so doctests will fail.
If you need to check if something is a number you need to check against both and under Python 2, but only in Python 3. The best way to do that is to set up a tuple depending on Python version and test against that. includes this:
>>> import sys >>> if sys.version_info < (3,): ... integer_types = (int, long,) ... else: ... integer_types = (int,) >>> isinstance(1, integer_types) True
2to3 fixer ☐ six support ☐
In Python 2 returns a list while in Python 3 it returns an iterator. will in some cases place a call around the call to to ensure that the result is still a list. If you need code that runs in both Python 2 and Python 3 without conversion and you need the result to be a list, you can do the same.
In Python 2 will continue until the longest of the argument iterables are exhausted, extending the other arguments with .
>>> def fun(a, b): ... if b is not None: ... return a - b ... return -a >>> map(fun, range(5), [3,2,1]) [-3, -1, 1, -3, -4]
In Python 3 will instead stop at the shortest of the arguments. If you want the Python 2 behavior in Python 3 you can use a combination of and .
>>> from itertools import starmap, zip_longest >>> def fun(a, b): ... if b is not None: ... return a - b ... return -a >>> list(starmap(fun, zip_longest(range(5), [3,2,1]))) [-3, -1, 1, -3, -4]
The Python 2 will accept as it’s function argument, where it will just return the object(s) passed in. As this transforms into it’s not particularly useful, and in Python 3 this no longer works. However, some code depends on this behavior, and you can use the following function as a full replacement for the Python 2 map.
from itertools import starmap, zip_longest def map(func, *iterables): zipped = zip_longest(*iterables) if func is None: # No need for a NOOP lambda here return zipped return starmap(func, zipped)
2to3 fixer ☑ six support ☑
In Python 2 you specified the metaclass with the attribute. In Python 3 you instead pass in a parameter in the class definition. Supporting metaclasses in Python 2 and Python 3 without using requires you to create classes on the fly. If you want this, I highly recommend to use the module, which has a very clever function.
2to3 fixer ☑ six support ☑
In Python 2 you get the next result from an iterator by calling the iterators method. In Python 3 there is instead a builtin.
If you need code that runs in both Python 2 and Python 3 without conversion you can make a function that under Python 2 calls and under Python 3 calls . The module contains such a function, called .
2to3 fixer ☐ six support ☐
In Python 2 you have parameter unpacking:
>>> def unpacks(a, (b, c)): ... return a,b,c >>> unpacks(1, (2,3)) (1, 2, 3)
Python 3 does not support this, so you need to do your own unpacking:
>>> def unpacks(a, b): ... return a,b[0],b[1] >>> unpacks(1, (2,3)) (1, 2, 3)
2to3 fixer ☑ six support ☑
The Python 2 statement is in Python 3 a function. If you need to run the same code in both Python 2 and Python 3 without conversion there are various techniques for this. This is discussed in detail in Supporting the print() function.
2to3 fixer ☑ six support ☑
In Python 2 the syntax for the statement is:
raise E, V, T
Where is a string, an exception class or an exception instance, the an optional exception value in the case that is a class or a string and is a object if you want to supply a traceback from a different place than the current code. In Python 3 this has changed to:
raise E(V).with_traceback(T)
As with the Python 2 syntax, and are optional. The syntax without the traceback variable is:
raise E(V)
This works in all versions of Python. It’s very unusual that you need the traceback parameter, but if you do and you also need to write code that runs under Python 2 and Python 3 without using you need to create different a function that takes , and as parameters and have different implementations under Python 2 and Python 3 for that function. The module has a nice implementation of that, called .
2to3 fixer ☑ six support ☑
In Python 2 returns a list, and returns an object that will only generate the items in the range when needed, saving memory.
In Python 3, the function is gone, and has been renamed . In addition the object supports slicing in Python 3.2 and later .
will in some cases place a call around the call to , to ensure that the result is still a list. If you need code that runs in both Python 2 and Python 3 without conversion and you need the result to be a list, you can do the same.
You can import from the module to be sure you get the iterator variation under both Python 2 and Python 3.
2to3 fixer ☑ six support ☐
In Python 2 you can generate a string representation of an expression by enclosing it with backticks:
>>> `sorted` '<built-in function sorted>' >>> `2+3` '5'
The only purpose with this syntax is to confuse newbies and make obfuscated Python. It has been removed in Python 3, since the builtin does exactly the same.
>>> repr(sorted) '<built-in function sorted>' >>> repr(2+3) '5'
2to3 fixer ☐ six support ☐
The behavior of has changed in Python 3. In Python 2, rounding of halfway cases was away from zero, and would always return a float.
>>> round(1.5) 2.0 >>> round(2.5) 3.0 >>> round(10.0/3, 0) 3.0
In Python 3 rounding of halfway cases are now always towards the nearest even. This is standard practice, as it will make a set of evenly distributed roundings average out.
When called without the second parameter, which determines the number of decimals, will in Python 3 return an integer. If you pass in a parameter to set the number of decimals to round to, the returned value will be of the same type as the unrounded value. This is true even if you pass in zero.
>>> round(1.5) 2 >>> round(2.5) 2 >>> round(10.0/3, 0) 3.0
If you need the Python 2 behavior, you can use the following method:
>>> import math >>> def my_round(x, d=0): ... p = 10 ** d ... if x > 0: ... return float(math.floor((x * p) + 0.5))/p ... else: ... return float(math.ceil((x * p) - 0.5))/p >>> my_round(1.5) 2.0 >>> my_round(2.5) 3.0 >>> my_round(10.0/3, 0) 3.0
2to3 fixer ☐ six support ☐
In Python 1 you used and to support slice methods like on your object. These were deprecated in Python 2.0 but still supported. Python 3 removes the support for the slice methods, so you need to instead extend , and with slice object support.
>>> class StrawberryTart(object): ... ... def __getitem__(self, n): ... """An example of how to use slice objects""" ... if isinstance(n, slice): ... # Expand the slice object using range() ... # to a maximum of eight items. ... return [self[x] for x in ... range(*n.indices(8))] ... ... # Return one item of the tart ... return 'A slice of StrawberryTart with ' \ ... 'not so much rat in it.' ... >>> tart = StrawberryTart() >>> tart[5:6] ['A slice of StrawberryTart with not so much rat in it.']
2to3 fixer ☐ six support ☐
In Python 2 the method on lists as well as the builtin takes two parameters, and . In Python 3 only the parameter is supported. There are no fixers for this, so you need to change that in the Python 2 code.
See When sorting, use key instead of cmp for more information.
2to3 fixer ☑ six support ☐
Python 2 has an exception class called that has been removed in Python 3. Use instead.
2to3 fixer ☑ six support ☑
Python 2 had two string types; and . Python 3 has only one; , but instead it also has a type made to handle binary data. For more information on this, see Bytes, strings and Unicode and More bytes, strings and Unicode.
Footnotes
The book gets right to the point, without a lot of fluff and fillerDoug Hellmann
A concise, well-organised and complete referenceRichard Jones
Enter search terms or a module, class or function name.