Built-In Function Changes¶
Python 3 saw some changes to built-in functions. These changes are detailed in this section.
The print()
function¶
- Fixer:
python-modernize -wnf libmodernize.fixes.fix_print
- Prevalence: Very Common
Before Python first introduced keyword arguments, and even functions with
variable numbers of arguments, it had the print
statement.
It worked for simple use cases, but grew idiosyncratic syntax for advanced
features like (not) ending lines and output to arbitrary files:
print 'a + b =',
print a + b
print >> sys.stderr, 'Computed the sum'
In Python 3, the statement is gone. Instead, you can use the print()
function, which has clear semantics (but requires an extra pair of
parentheses in the common case):
print('a + b =', end=' ')
print(a + b)
print('Computed the sum', file=sys.stderr)
The function form of print
is available in Python 2.6+, but to use it,
the statement form must be turned off with a future import:
from __future__ import print_function
The recommended fixer will add the future import and rewrite all uses
of print
.
Safe input()
¶
- Fixer:
python-modernize -wnf libmodernize.fixes.fix_input_six
- Prevalence: Uncommon
In Python 2, the function input()
read a line from standard input,
evaluated it as Python code, and returned the result.
This is almost never useful – most users aren’t expected to know Python syntax.
It is also a security risk, as it allows users to run arbitrary code.
Python 2 also had a sane version, raw_input()
, which read a line and
returned it as a string.
In Python 3, input()
has the sane semantics, and raw_input
was
removed.
The Compatibility library: six library includes a helper, six.moves.input
, that has the
Python 3 semantics in both versions.
The recommended fixer will import that helper as input
, replace
raw_input(...)
with input(...)
, and replace input(...)
with
eval(input(...))
.
After running it, examine the output to determine if any eval()
it produces is really necessary.
Removed file()
¶
- Fixer:
python-modernize -wnf libmodernize.fixes.fix_file
(but see below) - Prevalence: Rare
In Python 2, file()
was the type of an open file. It was used in two
ways:
- To open files, i.e. as an alias for
open()
. The documentation mentions thatopen
is more appropriate for this case. - To check if an object is a file, as in
isinstance(f, file)
.
The recommended fixer addresses the first use: it will rewrite all calls to
file()
to open()
.
If your code uses the name file
for a different function, you will need
to revert the fixer’s change.
The fixer does not address the second case. There are many kinds of file-like
objects in Python; in most circumstances it is better to check for
a read
or write
method instead of querying the type.
This guide’s section on strings even recommends using
the io
library, whose open
function produces file-like objects that
aren’t of the file
type.
If type-checking for files is necessary, we recommend using a tuple of types
that includes io.IOBase
and, under Python 2, file
:
import io
try:
# Python 2: "file" is built-in
file_types = file, io.IOBase
except NameError:
# Python 3: "file" fully replaced with IOBase
file_types = (io.IOBase,)
...
isinstance(f, file_types)
Removed apply()
¶
- Fixer:
python-modernize -wnf fissix.fixes.fix_apply
(but see below) - Prevalence: Common
In Python 2, the function apply()
was built in.
It was useful before Python added support for passing an argument list
to a function via the *
syntax.
The code:
arguments = [7, 3]
apply(complex, arguments)
can be replaced with:
arguments = [7, 3]
complex(*arguments)
The recommended fixer replaces all calls to apply
with the new syntax.
If the variable apply
names a different function
in some of your modules, revert the fixer’s changes in that module.
Moved reduce()
¶
- Fixer:
python-modernize -wnf fissix.fixes.fix_reduce
- Prevalence: Uncommon
In Python 2, the function reduce()
was built in.
In Python 3, in an effort to reduce the number of builtins, it was moved
to the functools
module.
The new location is also available in Python 2.6+, so this removal can be fixed by importing it for all versions of Python:
from functools import reduce
The recommended fixer will add this import automatically.
The exec()
function¶
- Fixer:
python-modernize -wnf fissix.fixes.fix_exec
- Prevalence: Rare
In Python 2, exec()
was a statement. In Python 3, it is a function.
There were three cases for the statement form of exec
:
exec some_code
exec some_code in globals
exec some_code in globals, locals
Similarly, the function exec
takes one to three arguments:
exec(some_code)
exec(some_code, globals)
exec(some_code, globals, locals)
In Python 2, the syntax was extended so the first expression may be a 2- or 3-tuple. This means the function-like syntax works even in Python 2.
The recommended fixer will convert all uses of exec
to the function-like
syntax.
Removed execfile()
¶
- Fixer: None recommended
- Prevalence: Very rare
Python 2 included the function execfile()
, which executed
a Python file by name.
The call:
execfile(filename)
was roughly equivalent to:
from io import open
def compile_file(filename):
with open(filename, encoding='utf-8') as f:
return compile(f.read(), filename, 'exec')
exec(compile_file(filename))
If your code uses execfile
, add the above compile_file
function to
an appropriate place, then change all calls to execfile
to exec
as above.
Although Automated fixer: python-modernize has an execfile
fixer, we don’t recommend
using it, as it doesn’t close the file correctly.
Note that the above hard-codes the utf-8
encoding (which also works if your
code uses ASCII).
If your code uses a different encoding, substitute that.
If you don’t know the encoding in advance, you will need to honor PEP 263
special comments: on Python 3 use the above with tokenize.open()
instead of open()
, and on Python 2 fall back to the old
execfile()
.
The io.open() function is discussed in this guide’s section on strings.
Moved reload()
¶
- Fixer: None
- Prevalence: Very rare
The reload()
function was built-in in Python 2.
In Python 3, it is moved to the importlib
module.
Python 2.7 included an importlib
module, but without a reload
function.
Python 2.6 and below didn’t have an importlib
module.
If your code uses reload()
, import it conditionally if it doesn’t exist
(using feature detection):
try:
# Python 2: "reload" is built-in
reload
except NameError:
from importlib import reload
Moved intern()
¶
- Fixer: None
- Prevalence: Very rare
The intern()
function was built-in in Python 2.
In Python 3, it is moved to the sys
module.
If your code uses intern()
, import it conditionally if it doesn’t exist
(using feature detection):
try:
# Python 2: "intern" is built-in
intern
except NameError:
from sys import intern
Removed coerce()
¶
- Fixer: None
- Prevalence: Rare
Python 3 removes the deprecated function coerce()
, which was only
useful in early versions of Python.
If your code uses it, modify the code to not require it.
If any of your classes defines the special method __coerce__
,
remove that as well, and test that the removal did not break semantics.