Writing compatible python2.x and 3.x code
When we're in the middle of a transition from Python 2.x to Python 3.x, you might want to be able to run in Python 2 and 3 at the same time without modifying any code. This may seem like a reasonable claim, but how do you start? What Python 2 code is easy to do when the 3.x interpreter executes?
Print vs print ()
If you think like me, you might say print, which is a good starting point, first of all, simply show that print is a statement in 2.x, and in 3.x it is a keyword or a reserved word. In other words, because this change involves the syntax of the language, you cannot use it in the IF statement, and Python still does not have #ifdef macros. Here, try to print out the parameters inside the brackets:
>>> print (' Hello world! ')
Hello world!
Cool, it works in both Python2 and Python3, and it works the same way, and look at the following paragraph:
>>> Print # Python 2
(10, 20)
At this point, you are not as lucky as before to get the same result, the Python2 print is a tuple (tuple), and in Python3 Pass multiple parameters to print () inside the print is two values:
>>> Print # Python 3
10 20
If you're thinking more, we can check if print is a keyword, and the keyword module contains a list of keywords. Print is not a keyword in 3.x and can be easily verified:
>>> Import keyword
>>> ' print ' in Keyword.kwlist
False
As a smart programmer, you might expect the result to be true when you try it in 2.x, although it's not wrong, but in order to achieve Python3 effect, you will still fail for other reasons.
>>> Import keyword
>>> if ' print ' in keyword.kwlist:
... From __future__ import print_function ...
File "", Line 2
syntaxerror:from __future__ imports must occur at the beginning of the file
One solution is to use a function that resembles print, one of which is sys.stdout.write () and the other is Distutils.log.warn (). For whatever reason, we decided to use the latter. The example of "Hello World" looks like this:
# Python 2.x
print ' Hello world! '
# Python 3.x
print (' Hello world! ')
The following code can be common in two versions:
# Python 2.x & 3.x compatible from
Distutils.log import warn as printf
printf (' Hello world! ')
Why don't we use Sys.stdout.write () because we need to add a newline character at the end of the string to be compatible with this behavior (the Write method in python2.x does not wrap):
# Python 2.x & 3.x compatible
import sys
sys.stdout.write (' Hello world!n ')
Import your way to a solution
Under normal circumstances, import is nothing to worry about, as long as the correct import on the line, but in the following code, we want to import the Urlopen () function, in the Python2, he also exists with URLLIB2 and URLLIB2 (we use the latter), in the Python3, He is integrated into the urllib.request, and your plan is to work in both 2.x and 3.x:
Try: From
urllib2 import urlopen
except Importerror: from
urllib.request import Urlopen
For memory protection, you may be more interested in the iterator (Python3) version of Zip (), and in Python2, the iterator version is Itertools.izip (). This function is renamed in Python3 and replaced with zip (). If you use an iteration version, the import statement is straightforward:
Try: From
itertools import izip as zip
except importerror:
Pass
Another is to appear not how elegant Stringio class, in Python2, the pure Python version is the Stringio module, This means that the visit is via Stringio.stringio, and there is also a faster C language version, located in Cstringio.stringio, but depending on your Python installation version, you can use Cstringio first and then Stringio (if Cstrin Gio can not be used). Unicode is the default string type in Python3, but if you do any network-related operations, it is likely that you will have to use a ascii/byte string to operate, so instead of Stringio, you want IO. Bytesio, in order to get what you want, this import looks a little ugly:
Try: From
io import bytesio as Stringio
except Importerror:
try: From
cstringio import Stringio
Except Importerror: from
stringio import Stringio
Putting it all together
If you're lucky, the above is all you have to do, and the rest of the code is simpler than where you started. If you import the Distutils.log.warn () [printf ()],url*urlopen (), * in the way above. Stringio and a standard import: Xml.etree.ElementTree (2.5 and newer), now you can write a very simple short parser to show the headline story from Google News Service (a ladder, of course), Just eight lines of code:
g = Urlopen (' Http://news.google.com/news?topic=h&output=rss ')
f = Stringio (G.read ())
g.close ()
Tree = Xml.etree.ElementTree.parse (f)
F.close () to
ELMT in Tree.getiterator ():
if Elmt.tag = = ' title ' and Not
elmt.text.startswith (' Top Stories '):
printf ('-%s '% elmt.text)
This script runs under 2.x and 3.x without any changes, and it works exactly the same, of course, if you're using a 2.4 or older version, you'll need to download elementtree separately.
But sometimes it feels like these changes are messing with your elegant Python code, and readability is the most important thing, if you want to prioritize the code and run it in two versions of Python without modifying anywhere, then you can look at the six package.
Six a compatible library, its main task is to provide an interface to hide complex details that you can find here. Whether you're using a library like six or doing it your own way, we hope this brief introduction allows you to start thinking about writing code that runs at the same time under 2.x and 3.x.