I am trying to make some of my code Python 2 and 3 compatible.
At the moment I am struggling with functions like range
/xrange
and methods like dict.items
/dict.iteritems
. Ideally I would like my code to be able to use the former in Python 3.x and the latter in Python 2.x.
Using if
/else
seems to me to be the easiest way to implement this:
if py >= 3:
for item in array.items()
...
else:
for item in array.iteritems()
However, doing like that results in lots of repeated and ugly code. Is there a better way to do that using only the standard library? Can I just state somewhere at the beginning of the code to always use range
/dict.items
if py >= 3
and xrange
/dict.iteritems
if not?
Is it possible to do something like this?
if py < 3:
use xrange as range
I have looked around and I know that several libraries, like six o futurize) are used to solve this issue. However I am working on a server that run only python 2.7 and I am not allowed to install any extra libraries on it. I have some python3 code I would like to use but I also want to maintain only one version of the code.
The latest stable version is Python 3.9 which was released in 2020. The nature of python 3 is that the changes made in python 3 make it incompatible with python 2. So it is backward incompatible and code written in python 3 will not work on python 2 without modifications.
Python 3 is not backwards compatible with Python 2, so your code may need to be adapted. Please start migrating your existing your existing Python 2 code to Python 3. Python 2 series End Of Life is set to 1st of January 2020.
Just open the python files in the pycharm editor, it will show warnings if the code is not compatible to Python2 or Python3. Here is the screenshot where it shows print command syntax warning.
The simple, "Don't Make Me Think!" solution I use is to start simple scripts with:
#!/usr/bin/env python
# just make sure that Python 3 code runs fine with 2.7+ too ~98% of the time :)
from __future__ import (division, print_function, absolute_import,
unicode_literals)
from builtins import int
try:
from future_builtins import ascii, filter, hex, map, oct, zip
except:
pass
import sys
if sys.version_info.major > 2:
xrange = range
(Extra tip to stop most pep8 linters for unnecessarily yelling at you for this: move last 3 lines inside and at the top of the try
block above)
But the only case I use this is basically "shell scripts that were too large and hairy so I quickly rewrote them to Python and I just want them to run under both Python 2 and 3 with 0 dependencies". Please do NOT use this in real application/library code until you know exactly what are the consequences of all the lines above, and if they are enough for your use case.
Also, the "solution" in this case for .iteritems
is "just don't use it", ignore memory use optimizations and just always use .items
instead - if this matters, it means you're not writing a "0 dependencies simple script" anymore, so just pick Python 3 and code for it (or Python 2 if you need to pretend we're in 2008).
Also, check these resources to get a proper understanding:
(NOTE: I'm answering this already answered question mainly because the accepted answers roughly translates to "you are stupid and this is dumb" and I find this very rude for an SO answer: no matter how dumb the question, and how "wrong" to actually answer it, a question deserves a real answer._
import sys
if sys.version_info.major > 2:
xrange = range
But as Wim implies, this is basically rewriting six yourself.
And as you can see, six
does a lot more that handling range
. Just e.g. look at the _moved_attributes
list in the six source code.
And while Python comes with "batteries included", its standard library is not and cannot be all-encompassing. Nor is it devoid of flaws.
Sometimes there are better batteries out there, and it would be a waste not to use them. Just compare urllib2
with requests
. The latter is much nicer to work with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With