Standard library incompatibilities

Some standard library interfaces have changed in ways that require different code than normal Py3 code in order to achieve Py2/3 compatibility.

Here we will attempt to document these, together with known workarounds:

Standard library incompatibilities

module

object / feature

section

array

array constructor

array.array()

array

array.read() method

array.array.read()

base64

decodebytes() function

base64.decodebytes() and base64.encodebytes()

re

ASCII mode

re.ASCII

To contribute to this list, please send a pull request. See Contributing.

array.array()

The first argument to array.array(typecode[, initializer]) must be a native platform string: unicode string on Python 3, byte string on Python 2.

Python 2::
>>> array.array(b'b')
array.array(b'b')
>>> array.array(u'u')
TypeError: must be char, not unicode
Python 3::
>>> array.array(b'b')
TypeError: must be a unicode character, not bytes
>>> array.array(u'b')
array('b')

This means that the typecode cannot be specified portably across Python 3 and Python 2 with a single string literal when from __future__ import unicode_literals is in effect.

You can use the following code on both Python 3 and Python 2:

from __future__ import unicode_literals
from future.utils import bytes_to_native_str
import array

# ...

a = array.array(bytes_to_native_str(b'b'))

This was fixed in Python 2.7.11. Since then, array.array() now also accepts unicode format typecode.

array.array.read()

This method has been removed in Py3. This crops up in e.g. porting http.client.

base64.decodebytes() and base64.encodebytes()

The base64 module on Py2 has no decodebytes or encodebytes functions.

re.ASCII

Python 3 code using regular expressions sometimes looks like this (from urllib.request):

re.compile(r":\d+$", re.ASCII)

This enables ‘ASCII mode’ for regular expressions (see the docs here). Python 2’s re module has no equivalent mode.

struct.pack()

Before Python version 2.7.7, the struct.pack() function required a native string as its format argument. For example:

>>> from __future__ import unicode_literals
>>> from struct import pack
>>> pack('<4H2I', version, rec_type, build, year, file_hist_flags, ver_can_read)

raised TypeError: Struct() argument 1 must be string, not unicode.

This was fixed in Python 2.7.7. Since then, struct.pack() now also accepts unicode format strings.