Skip to main content

Python 2 / 3 兼容性,类似 6,但有利于 Python 3

项目描述

让我们现在编写 Python 3!

当最好的 Python 2/Python 3 兼容性模块——尤其是 Benjamin Peterson 发明的著名的 *six* 库 ——被创建时,它们是从 Python 2 程序员开始了解 Python 3 的角度编写的。如果你使用6 个,您的代码是兼容的,但停留在 Python 2 习惯用法中。

颠倒。您尽可能多地使用 Python 3 惯用语编写代码,并且修补的是 Python 2“版本”。不用说,这种方法更具前瞻性。

当你编写 Python 时,你应该编写 Python 3,并确保在 Python 2.7 上运行一段时间。

促进了这一观点。您可以编写尽可能 3ish 的代码,同时仍支持 2.6。

例如,您不再键入unicode,而是键入str,并且在 Python 2 上, 使str指向unicode(如果您使用我们的样板)。此外,在 Python 2 上, mapzipfilter具有 Python 3 的行为,这意味着它们返回迭代器,而不是列表。

老实说,您不应该再花时间在 Python 2.6 上, 自 2013 年 10 月发布最终版本 (2.6.9) 以来,它不再受支持。也没有人使用 3.0 或 3.1。

Python 2.7 终于在 2020 年的第一天走向灭亡。

非常稳定,不太可能改变,因为它解决了一个永远不会改变的老问题。如果9个月甚至几年没有更新,没有人应该感到惊讶。

人的作者将此模块捐赠给公共领域。

要了解在单个代码库中实现 2&3 兼容性所涉及的大部分复杂性,我建议阅读以下内容:http: //lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/

使用九

在每个模块中,首先声明一个文本编码并从 __future__ 导入 Python 3 行为。然后根据这个样板文件从导入变量:

# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
from nine import (IS_PYTHON2, str, basestring, native_str, chr, long,
    integer_types, class_types, range, range_list, reraise,
    iterkeys, itervalues, iteritems, map, zip, filter, input,
    implements_iterator, implements_to_string, implements_repr, nine,
    nimport)

我知道那很丑。你期待什么?是 3 的平方。好的,在许多情况下,您可以少花钱:

# -*- coding: utf-8 -*-

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
from nine import IS_PYTHON2, nimport, nine, range, str, basestring

但是在第二种情况下,你需要记住在使用时导入丢失的东西,期望你会记住是不现实的,是吗?

统一码

由于unicode_literals导入,模块中的所有字符串文字都成为 unicode objects。无需为每个字符串文字添加“u”前缀。这是更明智的方法,因为在 Python 3 中,字符串默认是 unicode 对象,然后您可以指示b"this is a byte string literal"。实际上需要是字节字符串的文字是非常罕见的。但是你不会相信有多少开发人员无理地害怕采取这个简单的步骤......

如果您对 Unicode 不太了解,请阅读 每个软件开发人员绝对、肯定必须了解 Unicode 和字符集的绝对最低要求(没有借口!)

导入移动的东西

许多标准库模块在 Python 3 中被重命名,但有九个可以提供帮助。nimport函数获取新的 Python 3 名称,但如果在 Python 2 中运行,知道要导入旧名称。例如,不要编写此代码来导入 pickle:

# Bad:
try:
    import cPickle as pickle  # Python 2.x
except ImportError:
    import pickle  # Python 3 automatically uses the C version.

…你可以这样写:

# Good:
pickle = nimport('pickle')

对于已移动的变量:在参数中,请用冒号分隔模块和变量:

name2codepoint = nimport('html.entities:name2codepoint')

想要StringIO?我建议您改为建立列表。但如果你真的需要它:

# Good:
if IS_PYTHON2:
    from cStringIO import StringIO as BytesIO, StringIO
    NativeStringIO = BytesIO
else:
    from io import BytesIO, StringIO
    NativeStringIO = StringIO

我们对 Python 版本差异的报道可能并不详尽,但欢迎贡献。

如有疑问, 请使用来源

请参阅 GitHub 上的项目页面!我们还在 Travis-CI 进行持续集成

九班装饰

我们为魔术方法的 Python 2 和 3 兼容性提供了一个类装饰器。魔术方法是以两条下划线开头和结尾的方法。

您使用它们的 Python 3 名称定义魔术方法,并且在 Python 2 上,它们获得相应的名称。你可以写:

  • __next__()。使用next(iterator)函数进行迭代。

  • __str__():必须返回一个 unicode 字符串。在 Python 2 中,我们 根据您的__str__( ) 为您实现__unicode__()__bytes__ () 。

  • __repr__():必须返回一个 unicode 字符串。

  • __bytes__():必须返回一个字节对象。

例子:

@nine
class MyClass(object):

    def __str__(self):
        return "MyClass"  # a unicode string

移植步骤

当您开始在 Python 2 代码上应用9以实现 Python 3 兼容性时,您可以从以下任务列表开始。这并不详尽,只是一个好的开始。您可以一次升级一个.py模块:

  • 如上所述添加我们的标题。

  • 用 print 函数替换出现的 print 语句(这大致意味着,添加括号)。

  • 替换str(),通常用九的native_str()bytes()

  • str()from 9 import str替换unicode()

  • __str__()方法替换__unicode__( )方法;在类上应用@nine装饰器。

  • 还要在定义__repr__()的类上应用@nine装饰器。

  • 搜索范围并替换为九的范围range_list

  • 一些 dict 方法在 Python 3 中返回不同的东西。只有当您需要在两个版本中完全相同的行为时,才替换:

    • d.keys()d.iterkeys()与九个iterkeys(d)

    • d.values()d.itervalues()与九的itervalues(d) ; 和

    • d.items()d.iteritems()与九个iteritems(d)

  • 请注意,在九个版本中,map()zip()filter()始终返回独立于 Python 版本的迭代器。

如果您之前使用过六个或其他兼容性库:

  • 用九的基本字符串替换string_types

然后在您希望支持的所有 Python 版本中运行您的测试。

如果我忘了提什么,你 能提出一个拉取请求吗,为了其他开发人员的利益?

下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

9-1.1.0.tar.gz (9.8 kB 查看哈希

已上传 source

内置分布

9-1.1.0-py2.py3-none-any.whl (9.2 kB 查看哈希

已上传 3 7