可以从__future__导入...保证Python 2和3的兼容性吗?

时间:2012-06-19 14:25:52

标签: python python-3.x python-2.x

我对升级“Python 2或Python 3?”不感兴趣。问题(即使我发现the most recent one超过一年),但我偶然发现this claim

  

如果您的文件开始,您可以在Python 2下编写Python 3代码   与行:

from __future__ import absolute_import, division, generators, unicode_literals, print_function, nested_scopes, with_statement
     

使用该行,您的代码将使用Python 2或   Python 3.可能有少数情况下它不起作用,但我有   没找到,

这是真的吗?这一行是否足以确保您编写的代码将在Python 2.x(> =我假设为2.5)和3.x(假设导入的模块都可用)中运行?

6 个答案:

答案 0 :(得分:8)

我会说不,这是胡扯。即使使用这些导入,Python 2和3之间仍然存在显着差异:例如,Python 3中的input()与Python 2中的raw_input()类似; Python 3中的range()与Python 2中的xrange()类似。对于xrange(),只要范围很小,您就可以在Python 2中使用range()。但是如果它们很大,那么你的程序在Python 2和Python 3下的内存使用量会有很大差异。

您可以在代码中添加以下内容:

try:
    range = xrange
    input = raw_input
except NameError:
    pass

但是你必须找到所有这些边缘情况并修复它们。例如,keys()的{​​{1}}和values()方法在Python 3中返回迭代器但在Python 2中列出,因此您需要编写dict子类“修复”(然后在你的代码中不使用字典文字而不包装它们,因为否则它们将是内置的dict类型)。

我认为,通过使用dict和各种修复,并限制自己编写代码,这些代码可以在2.x和3.x下运行的Python子集中编写,它可能是可以编写在两个版本中运行的代码。看起来好像很多工作。有一个__future__实用程序......

的原因

答案 1 :(得分:7)

“这取决于”

否:将这些导入添加到Python 2代码中不会使其在Python 3下运行。

是的:使用这些导入,您可以编写在Python 2和Python 3下运行的代码。

但是:然后,你也可以在没有这些导入的情况下做到这一点,其中一些,例如unicode_literals已经证明根本没有帮助。 generatorswith_statement根本不涉及Python 2到Python 3,这些是Python 2版本中添加的功能。

总而言之,这些进口产品有点像红鲱鱼,而且这种说法比错误做得更糟。

然而,并不意味着编写在Python 2和Python 3下运行的代码是不可能的,甚至是非常困难的。有关详细信息,请参阅http://python3porting.com/

答案 2 :(得分:5)

根据您的代码库的需求,这并非不可能。您可能会发现six(2 * 3,哈哈)库至关重要;另一个有用的工具是python-modernize,它试图将代码转换为交叉兼容状态。

答案 3 :(得分:4)

它会使它更有可能,但有些东西无法通过__future__导入获得,有些东西会被移除到3.x.

在我的头顶,您仍然可以使用参数元组解包,这在3.x中删除,并且您将无法使用3.x中引入的星形运算符的好元组解包

E.g:

def some_function((x, y), magnitude): #This has been removed in 3.x
    pass

x, *y = (1, 2, 3) #This does not exist in 2.x

也就是说,小心翼翼地避免这样的事情,你绝对可以编写适用于这两个版本的代码,是的。

显然,这也仅适用于具有向后移植到其中的功能的2.x版本。因此,该行的某些内容实际上完全没有意义 - 例如,没有理由导入generators,因为任何可以导入with语句的版本都已经将生成器作为标准工作。同样适用于nested_scopes

一般来说,我建议只为3.x编写 - 安装和使用这两个版本没有任何障碍。如果您真的非常需要2.x支持,那么请使用尽可能多的后端移植功能为2.x写入,并使用2to3来清理其他任何内容。

答案 4 :(得分:3)

罗。其他人指出了一些差异,还有其他人。其中最基本的一点是Python 3本机字符串是多字节的 - 这在与单字节机制进行通信时会产生问题,例如管道到其他进程。其他包括重命名模块(Tkinter到tkinter),True和False现在是关键字。

即使比较可能也不一样,以下错误代码:

num = 42
txt = "3"

if txt < num:
    print ('Wow!')
else:
    print ('Doh!')

在Py3上产生TypeError,但在Py2上没有。

已提及拆包。字典方法items()keys()values()返回视图对象(2.7上使用不同的方法名称)。在Py3中使用的迭代器更多,例如从map()filter()返回,依此类推....

答案 5 :(得分:1)

您可以使用 future / 包: pip install future

In [1]: range(10)
Out[1]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [2]: from future.builtins import range

In [3]: range(10)
Out[3]: range(0, 10)

以下是他们的备忘单,其中包含更多示例:http://python-future.org/compatible_idioms.html