Python2/3兼容是可行的,许多库为了只维护一套代码,也是利用一些兼容库做到Python2/3兼容。虽然有2to3, 3to2, 2to6之类的代码转换工具,但是基本没什么人用,转出来也有许多问题。Python社区一般还是手工写同时兼容Python2/3的代码(这点和transpiler满天飞的JS社区很不同)。

__future__

python3出来的时候,python的设计者们当然也考虑过代码之间的兼容问题。许多为为兼容性设计的功能可以通过__future__这个包来导入。例如:

from __future__ import print_function

使用python3的print函数,禁用python2的print语句。

from __future__ import unicode_literal

像python3一样,字符串字面量的类型为文本(python2中的unicode,python3中的str),而不是字节(python2中的str,python3中的bytes)。

from __future__ import absolute_import

from __future__ import division

像python3一样,int除以int得float,而不像Python2那样是整除

导入这四个功能后,很多语法就和Python3中差不多了。

six

只用__future__是不够的,Python2/3之间还有别的差异。用six这个第三方模块可以解决这个问题(这里应该批评一下Python设计者们,这本应该是他们考虑的问题)。

例如,Python2和Python3中字符串类型名字不同,six可以把它们变成了统一的第三种形式(知乎怎么不支持表格啊):

equation?tex=%5Cbegin%7Barray%7D%7Blcc%7D+%E5%AD%97~~%E7%AC%A6~~%E4%B8%B2~~%E7%B1%BB~~%E5%9E%8B+%26+%E6%96%87~~%E6%9C%AC+%26+%E5%AD%97~~%E8%8A%82+%5C%5C+%5Cmathrm%7BPython2%7D+%26+%5Cmathrm%7Bunicode%7D+%26+%5Cmathrm%7Bstr%7D+%5C%5C+%5Cmathrm%7BPython3%7D+%26+%5Cmathrm%7Bstr%7D+%26+%5Cmathrm%7Bbytes%7D+%5C%5C+%5Cmathrm%7Bsix%7D+%26+%5Cmathrm%7Bsix.text%5C_type%7D+%26+%5Cmathrm%7Bsix.binary%5C_type%7D+%5Cend%7Barray%7D

例如,python2原来这么写:

if isinstance(xxx, unicode):

...

改成这样就可以同时兼容Python2/3:

import six

...

if isinstance(xxx, six.text_type):

...

six还能处理包名或者函数名不同的情况,例如Python2中的raw_input函数在Python3中变成了input函数。则可以从six中导入同时兼容Python2/3的input函数:

from six.moves import input

虽然利用__future__和six,可以写出同时兼容Python2/3的程序。但我觉得这样看上去未免会使程序变得丑陋,而且很多Python3的新特性还没法用了(例如asyncio, Type Hinting, f-string等)。所以还是希望Python3能够普及。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐