最好的方法只是用普通标准库编写Python 2和3兼容代码

问题描述 投票:8回答:5

我试图让我的一些代码,Python 2和3兼容。

目前,我与像range / xrange和像dict.items / dict.iteritems方法功能挣扎。理想情况下,我想我的代码,以便能够使用在Python 3.x中前者与后者在Python 2.x中

使用if / else在我看来,要实现这个最简单的方法:

if py >= 3:
    for item in array.items()
    ...
else:
    for item in array.iteritems()

但是,做这样导致大量的重复的和丑陋的代码。有没有更好的办法做到这一点只使用标准库?可我只是说出某个地方在代码的开头总是使用range / dict.items如果py >= 3xrange / dict.iteritems如果不是?

是否有可能做这样的事情?

if py < 3:
    use xrange as range

我环顾四周,我知道那几个库,例如六点futurize)被用来解决这个问题。但是我的工作仅运行Python 2.7版的服务器上,我不能在上面安装任何额外的库。我有一些python3代码,我想用,但我也想保持只有一个版本的代码。

python python-2.7 python-3.x compatibility
5个回答
10
投票
import sys

if sys.version_info.major > 2:
    xrange = range

但作为维姆意味着,这基本上是自己改写six

正如你所seesix做了很多更多的处理range。只是如看看六个源代码_moved_attributes列表。

虽然Python带有“电池列入”,其标准库是不是也不可能是全面的。也不是没有缺点的。

有时有更好的电池在那里,这将是一种浪费不使用它们。只是urllib2比较requests。后者是好得多的工作。


10
投票

简单,“不要让我想想!”解决办法我用的是开始简单的脚本有:

#!/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

(额外的尖端停止最PEP8棉短绒在你不必要喊这样的:移动最后3行内和在高于try块的顶部)

但是我用这唯一的情况下,基本上是“那是太大,多毛,所以我很快改写了他们的Python,我只是希望他们既Python 2和3 0依赖下运行shell脚本”。请直到你知道什么是最重要的行的后果,如果他们有足够为您的使用情况下,不要在真正的应用程序/库代码中使用此。

此外,“办法”在这种情况下.iteritems“只是不使用它”,忽略了内存使用的优化,只是始终使用.items而不是 - 如果此问题,它意味着你不是在写一个“0依赖简单的脚本”了,所以只挑的Python 3和代码它(或Python 2,如果你需要假装我们是在2008年)。

此外,检查这些资源得到一个正确的认识:


(注:我回答这个已经回答了问题,主要是因为接受的答案大致翻译为“你是愚蠢的,这是愚蠢的”,我觉得这对于一个非常粗鲁的SO回答:无论多么愚蠢的问题,以及如何“错“实际上回答这个问题,一个问题值得一个真正的answer._


3
投票

我建议写在你的项目的模块PY2或PY3,而不是它们混合在一起,并没有包括任何种类的2/3检查的。你的程序的逻辑不应该有可能关心其Python版本,除了避免对内置对象发生冲突的功能。

取而代之的是,从你自己的兼容层导入*能解决你的框架和利用之间的差异阴影,使之透明,以你的实际项目中的模块。

例如,兼容性模块中,你可以写罗兰·斯密的范围/ x范围substition,并在其他模块你“从兼容性进口*”添加。这样,每一个模块可以使用“x范围”和兼容层将管理2/3的差异。

不幸的是它不会解决现有对象的功能,如dict.iteritems;通常你会猴子修补字典方法,但它是不可能在内建类型(见https://stackoverflow.com/a/192857/1741414)。我可以想像一些解决方法:

  • 功能包装(主要是sobolevn的答案)
  • 不要使用.items()的所有功能;使用上的按键简单的循环,然后访问字典,这些按键:
    for key in my_dict:
        value = my_dict[key]
        # rest of code goes here

1
投票

我猜你是arraydict混淆在这种情况下。

如果您在使用3-d党库,以任何理由,那么为什么不喜欢这样的限制:

def iterate_items(to_iterate):
    if py >= 3:
        return to_iterate.items()
    else:
        return to_iterate.iteritems()

然后用它:

for item in iterate_items(your_dict):
    ...

-1
投票
import sys
VERSION = float("{}.{}".format(sys.version_info.major, sys.version_info.minor))

并利用这一点,我们可以写所需版本的条件代码。

if VERSION >= 3.5:
     from subprocess import run as _run
else:
     from subprocess import call as _run
© www.soinside.com 2019 - 2024. All rights reserved.