Public
Snippet $349 authored by Bryton Lacquement

Python 2.7 / 3.5 Compatibility

Edited
foo.md

Useful links:

General idea

For the moment, we want a transition step where the code is both Python 2 and 3 compatible. The general idea is to "patch" the code so as to have the least amount of work when switching to Python 3 only. For instance, when using six.moves:

  1. from six.moves import PY3name
  2. from six.moves import foo as PY3name
  3. from six.moves import foo as PY2name

Example of recurrent issues (non-exhaustive list, also serves as a guideline):

from six.moves.urllib import parse
import six; six.iterkeys(...);
from six.moves import configparser
from six.moves.urllib.request import urlopen

from six.moves import (
  http_client as httplib,
  xmlrpc_client as xmlrpclib,
)

from zope.interface import implementer
@implementer(...)

subprocess.Popen(..., universal_newlines=True, ...)

Strings and encoding

From https://docs.python.org/3/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit:

Everything you thought you knew about binary data and Unicode has changed.

  • Python 3.0 uses the concepts of text and (binary) data instead of Unicode strings and 8-bit strings. [...]
  • [...]
  • As the str and bytes types cannot be mixed, you must always explicitly convert between them. Use str.encode() to go from str to bytes, and bytes.decode() to go from bytes to str. You can also use bytes(s, encoding=...) and str(b, encoding=...), respectively.
  • [...]

TL;DR

binary (b"") text (u"")
Python 2 bytes, str, "" unicode
Python 3 bytes str, ""
Python 2 Python 3
>>> b'foo' == u'foo' True False