Portable python
When writing python code I try to write code which will run both on python2 and python3. Below is a list of items I regularly use.
I know there is a module named ‘six’ which probably also handles some of these cases, I still need to look into that.
Detecting version
There are several ways of detecting the python version:
platform.python_version() < '3.0'
sys.version_info[0] == 2
sys.version_info < (3, 0)
try:
import mod1
except:
import mod2
try:
name
except NameError:
name = something
__future__
from __future__ import division, print_function
StringIO
if sys.version_info[0] == 2:
from StringIO import StringIO
else:
from io import StringIO
from io import BytesIO
long
if sys.version_info[0] == 3:
long = int
stdin
if sys.version_info[0] == 2:
stdin = sys.stdin
else:
stdin = sys.stdin.buffer
xrange
if sys.version_info[0] == 3:
xrange = range
reload
if sys.version_info[0] == 3:
import imp
reload = imp.reload
builtins
if sys.version_info[0] == 2:
import __builtin__
else:
import builtins as __builtin__
utf8
if sys.version_info[0] == 2:
reload(sys)
sys.setdefaultencoding('utf-8')
bytes
if sys.version_info[0] == 2:
bytes = bytearray
unicode
if sys.version_info[0] == 3:
unicode = str
single byte
bytes((a,))
or
struct.pack("B", a)
join bytearrays
in python3 this is no problem, in python2 it does not work.
characters
Use slices instead of a single index to access single bytes:
if data[1:2] == b'a':
print("the 2nd byte is an 'a'")
unittest2
if sys.version_info < (2, 7):
import unittest2 as unittest
else:
import unittest
ConfigParser
if sys.version_info[0] == 2:
from ConfigParser import ConfigParser
else:
from configparser import ConfigParser
urlopen
if sys.version_info[0] == 2:
from urllib2 import urlopen
else:
from urllib.request import urlopen
Request
if sys.version_info[0] == 3:
import urllib.request
from urllib.request import Request
urllib2 = urllib.request
else:
import urllib2
from urllib2 import Request
start_new_thread
if sys.version_info[0] == 2:
from thread import start_new_thread
else:
from _thread import start_new_thread
scandir
import os
if sys.version_info[0] == 2:
import scandir
os.scandir= scandir.scandir
iterators
def next(self): return self.__next__()
In python2 print will eval and print arguments in order, while in python3
all arguments are evaluated first, and then printed.
Even with __future__.print_function
datetime.timezone.utc
if sys.version_info[0] == 2:
stdin = sys.stdin
class DummyTimezone:
class UTC(datetime.tzinfo):
def utcoffset(self, dt): return timedelta(minutes=-399)
utc = UTC()
datetime.timezone = DummyTimezone