Since Django doesn't yet support Python 3.x, I'm using Python 2.7. However, I'd like to go ahead and start familiarizing myself with the new Python 3.x syntax as much as possible. Which le开发者_JAVA百科ads me to the question:
- What is the best way to write Python 2.7 code that will be as compatible as possible with Python 3.x?
I know that running python -3
will
Warn about Python 3.x incompatibilities that 2to3 cannot trivially fix.
However, I'm interested in getting used to Python 3.x syntax while still using Python 2.7.
For instance, it seems that I should be using the following imports to my code:
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import
The above four __future__ import
statements are required as of Python 3.0, but not required in 2.7 as described in Python 2.7.3's documentation 27.11. Future Statement Definitions
What else?
Many modules these days get rewritten in a way that allows execution on both Python 2 and Python 3. This turns out to be not very hard at all, and in the future it will be very easy to just drop Python 2 support.
Take a look at the six module that helps with this task, encapsulating many of the differences in a convenient way:
Six provides simple utilities for wrapping over differences between Python 2 and Python 3.
Its website (and of course, code) lists a lot of ways to make this possible.
Put the following code into a py3k.py
module and import it like this:
from py3k import *
. You need to put it in every file though, but you can even leave it there if nobody uses Python 2.x anymore or you could just search & replace the import line with whitespace and then remove the file.
try:
from future_builtins import *
except ImportError:
pass
try:
input = raw_input
range = xrange
except NameError:
pass
And this is how my template file looks:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
"""
from __future__ import division, absolute_import, \
print_function, unicode_literals
from utils.py3k import * # @UnusedWildImport
#
You also need to use the new exception syntaxes, ie no more
try:
raise Exception, "Message"
except Exception, e:
pass
instead you should do:
try:
raise Exception("Message")
except Exception as e:
pass
Also make sure you prefix all your binary strings with a b, ie:
b'This is a binary string'
For a more complete cover of this topic, see http://python3porting.com/noconv.html
Many Python IDE's can be of big help here.
PyCharm, for example, can be configured to check for compatibility with any range of versions,
and report issues at any level of severity:
try:
input = raw_input
range = xrange
except NameError:
pass
Are two ones that spring to mind...
I propose you to give a try for future library. From their site:
python-future is the missing compatibility layer between Python 2 and Python 3. It allows you to use a single, clean Python 3.x-compatible codebase to support both Python 2 and Python 3 with minimal overhead.
It provides future and past packages with backports and forward ports of features from Python 3 and 2. It also comes with futurize and pasteurize, customized 2to3-based scripts that helps you to convert either Py2 or Py3 code easily to support both Python 2 and 3 in a single clean Py3-style codebase, module by module.
Notable projects that use python-future for Python 2/3 compatibility are Mezzanine and ObsPy.
Avoing range()
and zip()
, using xrange()
and itertools.izip()
instead.
精彩评论