使用标准库

时间:2015-05-24 10:36:34

标签: python python-2.7 python-3.x compatibility

我正在努力使我的一些代码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()

然而,这样做会导致大量重复和丑陋的代码。是否有更好的方法仅使用标准库?如果rangedict.items / py >= 3,我可以在代码开头的某个地方声明始终使用xrange / dict.iteritems如果没有?

是否可以做这样的事情?

if py < 3:
    use xrange as range

我环顾四周,我知道有几个图书馆,比如六个图书馆,用来解决这个问题。但是我正在使用只运行python 2.7的服务器,我不允许在其上安装任何额外的库。我有一些我想使用的python3代码,但我也想只维护一个版本的代码。

5 个答案:

答案 0 :(得分:9)

简单,&#34;不要让我思考!&#34;我使用的解决方案是使用以下命令启动简单脚本:

#!/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短裤因为不必要地对你大喊大叫:在上方try区块的内部和顶部移动最后3行

但是我使用它的唯一情况基本上是#34; shell脚本太大而且毛茸茸所以我很快将它们重写为Python,我只是希望它们在Python 2下运行3有0依赖&#34;。 请不要在实际的应用程序/库代码中使用它,直到您知道完全上述所有行的后果,以及它们是否足以满足您的使用情况。< / p>

此外,&#34;解决方案&#34;在这种情况下,.iteritems是&#34;只是不使用它&#34;,忽略内存使用优化,而始终使用.items代替 - 如果这样重要的是,这意味着你不会写一个&#34; 0依赖简单脚本&#34;所以,只需选择Python 3和代码(如果你需要假装我们在2008年的话,就选择Python 2)。

另外,请检查这些资源以获得正确的理解:

注意:我回答这个已经回答的问题主要是因为接受的答案大致翻译为&#34;你是愚蠢的,这是愚蠢的&#34;我发现这个<对于一个SO答案来说,非常粗鲁:无论问题多么愚蠢,以及如何错误地实际回答它,一个问题都值得一个真正的答案._

答案 1 :(得分:8)

import sys

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

但正如Wim所暗示的那样,基本自己重写six

正如你可以seesix处理range的工作要多得多。只是例如查看六个源代码中的_moved_attributes列表。

虽然Python附带&#34;电池包括&#34;,但它的标准库不是也不能包罗万象。它也没有缺陷。

有时会有更好的电池,不使用它们会浪费。只需将urllib2requests进行比较即可。后者更好可以使用。

答案 2 :(得分:3)

我建议在项目的模块中编写py2或py3,但不能将它们混合在一起,根本不包括任何类型的2/3检查。你的程序逻辑不应该关心它的python版本,除非是为了避免内置对象上的冲突函数。

相反,从您自己的兼容层导入*,修复框架之间的差异并使用阴影,使其对您的实际项目模块透明。

例如,在兼容性模块中,您可以为范围/ xrange编写Roland Smith的替代,并在其他模块中添加&#34;来自兼容性导入*&#34;。这样做,每个模块都可以使用&#34; xrange&#34;兼容层将管理2/3的差异。

不幸的是,它不能解决现有的对象函数,例如dict.iteritems;通常你会修补dict方法,但在内置类型上是不可能的(参见https://stackoverflow.com/a/192857/1741414)。我可以想象一些解决方法:

  • 功能包装(基本上是sobolevn的回答)
  • 根本不使用.items()函数;在键上使用简单循环,然后使用这些键访问字典:
    for key in my_dict:
        value = my_dict[key]
        # rest of code goes here

答案 3 :(得分:1)

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

如果您出于任何原因限制使用三维派对库,那么为什么不喜欢这样:

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

然后使用它:

for item in iterate_items(your_dict):
    ...

答案 4 :(得分:-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