Warning
This documentation is for an old version of IPython. You can find docs for newer versions here.
Writing code for Python 2 and 3¶
-
IPython.utils.py3compat.
PY3
¶ Boolean indicating whether we’re currently in Python 3.
Iterators¶
Many built in functions and methods in Python 2 come in pairs, one
returning a list, and one returning an iterator (e.g. range()
and
xrange()
). In Python 3, there is usually only the iterator form,
but it has the name which gives a list in Python 2 (e.g. range()
).
The way to write compatible code depends on what you need:
- A list, e.g. for serialisation, or to test if something is in it.
- Iteration, but it will never be used for very many items, so efficiency isn’t especially important.
- Iteration over many items, where efficiency is important.
list | iteration (small) | iteration(large) |
---|---|---|
list(range(n)) | range(n) | py3compat.xrange(n) |
list(map(f, it)) | map(f, it) | – |
list(zip(a, b)) | zip(a, b) | – |
list(d.items()) | d.items() | py3compat.iteritems(d) |
list(d.values()) | d.values() | py3compat.itervalues(d) |
Iterating over a dictionary yields its keys, so there is rarely a need
to use dict.keys()
or dict.iterkeys()
.
Avoid using map()
to cause function side effects. This is more
clearly written with a simple for loop.
Changed standard library locations¶
Several parts of the standard library have been renamed and moved. This
is a short list of things that we’re using. A couple of them have names
in IPython.utils.py3compat
, so you don’t need both
imports in each module that uses them.
Python 2 | Python 3 | py3compat |
---|---|---|
raw_input() |
input | input |
__builtin__ |
builtins | builtin_mod |
StringIO |
io | |
Queue |
queue | |
cPickle |
pickle | |
thread |
_thread | |
copy_reg |
copyreg | |
urlparse |
urllib.parse | |
repr |
reprlib | |
Tkinter |
tkinter | |
Cookie |
http.cookie | |
_winreg |
winreg |
Be careful with StringIO: io.StringIO
is available in Python 2.7,
but it behaves differently from StringIO.StringIO
, and much of
our code assumes the use of the latter on Python 2. So a try/except on
the import may cause problems.
-
IPython.utils.py3compat.
input
()¶ Behaves like
raw_input()
on Python 2.
Unicode¶
Always be explicit about what is text (unicode) and what is bytes. Encoding goes from unicode to bytes, and decoding goes from bytes to unicode.
To open files for reading or writing text, use io.open()
, which is
the Python 3 builtin open
function, available on Python 2 as well.
We almost always need to specify the encoding parameter, because the
default is platform dependent.
We have several helper functions for converting between string types. They all
use the encoding from IPython.utils.encoding.getdefaultencoding()
by default,
and the errors='replace'
option to do best-effort conversions for the user’s
system.
-
IPython.utils.py3compat.
unicode_to_str
(u, encoding=None)¶ -
IPython.utils.py3compat.
str_to_unicode
(s, encoding=None)¶ Convert between unicode and the native str type. No-ops on Python 3.
-
IPython.utils.py3compat.
str_to_bytes
(s, encoding=None)¶ -
IPython.utils.py3compat.
bytes_to_str
(u, encoding=None)¶ Convert between bytes and the native str type. No-ops on Python 2.
-
IPython.utils.py3compat.
cast_unicode
(s, encoding=None)¶ -
IPython.utils.py3compat.
cast_bytes
(s, encoding=None)¶ Convert strings to unicode/bytes when they may be of either type.
-
IPython.utils.py3compat.
cast_unicode_py2
(s, encoding=None)¶ -
IPython.utils.py3compat.
cast_bytes_py2
(s, encoding=None)¶ Convert strings to unicode/bytes when they may be of either type on Python 2, but return them unaltered on Python 3 (where string types are more predictable).
-
IPython.utils.py3compat.
unicode_type
¶ A reference to
str
on Python 3, and tounicode
on Python 2.
-
IPython.utils.py3compat.
string_types
¶ A tuple for isinstance checks:
(str,)
on Python 3,(str, unicode)
on Python 2.
Relative imports¶
# This makes Python 2 behave like Python 3:
from __future__ import absolute_import
import io # Imports the standard library io module
from . import io # Import the io module from the package
# containing the current module
from .io import foo # foo from the io module next to this module
from IPython.utils import io # This still works
Print function¶
# Support the print function on Python 2:
from __future__ import print_function
print(a, b)
print(foo, file=sys.stderr)
print(bar, baz, sep='\t', end='')
Metaclasses¶
The syntax for declaring a class with a metaclass is different in Python 2 and 3. A helper function works for most cases:
-
IPython.utils.py3compat.
with_metaclass
()¶ Create a base class with a metaclass. Copied from the six library.
Used like this:
class FormatterABC(with_metaclass(abc.ABCMeta, object)): ...
Combining inheritance between Qt and the traitlets system, however, does not work with this. Instead, we do this:
class QtKernelClientMixin(MetaQObjectHasTraits('NewBase', (HasTraits, SuperQObject), {})):
...
This gives the new class a metaclass of MetaQObjectHasTraits
,
and the parent classes HasTraits
and
SuperQObject
.
Doctests¶
-
IPython.utils.py3compat.
doctest_refactor_print
(func_or_str)¶ Refactors print statements in doctests in Python 3 only. Accepts a string or a function, so it can be used as a decorator.
-
IPython.utils.py3compat.
u_format
(func_or_str)¶ Handle doctests written with
{u}'abcþ'
, replacing the{u}
withu
for Python 2, and removing it for Python 3.Accepts a string or a function, so it can be used as a decorator.
Execfile¶
-
IPython.utils.py3compat.
execfile
(fname, glob, loc=None)¶ Equivalent to the Python 2
execfile()
builtin. We redefine it in Python 2 to better handle non-ascii filenames.
Miscellaneous¶
-
IPython.utils.py3compat.
safe_unicode
(e)¶ unicode(e) with various fallbacks. Used for exceptions, which may not be safe to call unicode() on.
-
IPython.utils.py3compat.
isidentifier
(s, dotted=False)¶ Checks whether the string s is a valid identifier in this version of Python. In Python 3, non-ascii characters are allowed. If
dotted
is True, it allows dots (i.e. attribute access) in the string.
-
IPython.utils.py3compat.
getcwd
()¶ Return the current working directory as unicode, like
os.getcwdu()
on Python 2.
-
IPython.utils.py3compat.
MethodType
()¶ Constructor for
types.MethodType
that takes two arguments, like the real constructor on Python 3.