Stop writing Python 4 incompatible code
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Wed Jan 13 02:30:19 EST 2016
Quote:
With the end of support for Python 2 on the horizon (in 2020),
many package developers have made their packages compatible
with both Python 2 and Python 3 by using constructs such as:
if sys.version_info[0] == 2:
# Python 2 code
else:
# Python 3 code
[...]
Another example of problematic code is the following:
if six.PY2:
# Python 2 code
elif six.PY3:
# Python 3 code
In this case, no code will get executed on Python 4 at all!
[end quote]
http://astrofrog.github.io/blog/2016/01/12/stop-writing-python-4-
incompatible-code/
or http://tinyurl.com/jskt54s
Better still, don't do version checks *at all*. There is almost never any
need for a version check. Better is to use feature detection:
try:
xrange # Succeeds in Python 2.
except NameError:
xrange = range
Not only is this almost entirely future-proof[1] and avoids overly-specific
version tests, but if your code happens to find itself running in a
customized environment which has already monkey-patched builtins to re-add
xrange, the first lookup will succeed and no extra work need be done.
You can be extremely fine-grained too:
try:
casefold = str.casefold # Succeeds in Python 3.3 or better
else:
casefold = str.lower # Poor Man's case-folding.
# Or if you prefer:
def casefold(s):
...
About the only thing I use version checking for is to decide which prompt I
want to use:
if sys.version_info[0] >= 3 and os.name == 'posix':
# Make the main prompt bold in Python 3. This probably won't
# work on Windows, put it should(?) work on any POSIX system.
sys.ps1 = '\001\x1b[1m\002py> \001\x1b[0m\002'
else:
sys.ps1 = 'py> '
In Python 3, that highlights the prompt py> in bold.
You can detect the return type:
if isinstance(map(len, []), list):
print("Python 2 version of map")
else:
# Python 3, or Python 2 with future_builtins.
print("Python 3 version of map")
and even the number and kind of arguments:
try:
sorted([], cmp=None)
except TypeError:
print("use key not cmp in Python 3")
_sorted = sorted
def sorted(L, cmp=None):
if cmp is None:
return _sorted(L)
return _sorted(L, key=functools.cmp_to_key(cmp))
So remember, use feature detection, not version checking.
[1] It might fail if some distant version of Python adds an xrange which
does something completely unexpected, or if it removes range; but surely
nobody can be expected to write forward-compatible code in the face of
changes of that magnitude.
--
Steve
More information about the Python-list
mailing list