目录

    Python2 到 Python3 是一个较大的版本更新。目前,生产环境依然有大量项目使用的是 Python2。但,这并不意味着项目会一直停留在 Python2,开发者也需要考虑项目对 Python3 的兼容性,以方便迁移,同时也是对新知识的学习。下面是一些学习的知识点整理。

    1. Python2 升级 Python3

    贸然地升级 Python3 ,无疑将会面临巨大风险。充分地了解 Python2 和 Python3 的区别,学习 Python3 的新特性,预留时间,制定升级计划是必须的。

    • 单元测试。 单元测试能跑通,是平稳升级的重要保障。单元测试能够验证升级前后,功能是否一致。如果项目没有单元测试,那么在升级之前应该补上。
    • py2 → six → py3。 升级到 Python3,最大的难点在于,改变开发人员的使用习惯。比如,在 Python2 中推荐的 xrange, 在 Python3 中却不能用。开发人员需要一个学习和适应的过程。推荐的策略是,新的功能代码兼容 Python3,逐步重构存量代码。

    2. __future__ 模块

    Python 的新版本会引入新的特性,但是,实际上这些特性在上一个版本中就已经存在。要使用某一新的特性,可以通过导入 __future__ 模块来实现。

    __future__ 包括下面几个新特性:

    上面,表中第一列包含了所有可以从 __future__ 中导入的特性,optional in 中的版本号为最低可使用的版本,mandatory in 中的版本号为已经实现,无需从 __future__ 导入的版本号。最后一列是每个新特性所对应的 PEP 及简单描述。下面是部分 Python3 的新特性示例:

    2.1 打印函数

    使用 Python3 的 print 函数,禁用 Python2 的 print 语句

    from __future__ import print_function
    print(123)
    123
    

    2.2 文本字符串

    字符串字面量的类型为文本(Python2 中的 unicode,Python3 中的 str),而不是字节(Python2中的 str,Python3 中的 bytes)。

    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals
    print('试试看')
    

    2.3 引入模块时,优先绝对路径

    使用绝对路径导入模块时,Python 会在 sys.path 里寻找模块。

    在Python 2.4 或之前, Python 会先查找当前目录下有没有模块, 若找到了,则引入该模块。

    from __future__ import absolute_import
    

    2.4 使用浮点除法

    Python3 中 int 除以 int 得float,而 Python2 使用的是整除。

    from __future__ import division
    print 3/2
    1.5
    

    3. six 模块

    six 是一个专门用来兼容 Python 2 和 Python 3 的库。six 重新定义了在 Python2 和 Python3 中有差异的函数,six 会根据 Python 解释器的版本调用合适的处理函数。

    3.1 常量定义兼容

    • six.PY2/ six.PY3 ,布尔值。检查编译器版本是否为 Python2 或 Python3
    • six.class_types,类类型。在 Python2 中包含旧类和新类。在 Python3 中只是新类
    • six.integer_types,整数类型。在 Python2 中是 long 或 int,在 Python3 中是 int
    • six.string_types,文本数据的类型。Python2 中是 basestring() , Python3 中是 str
    • six.text_type,用于表示(Unicode)文本数据的类型。Python2 中是 unicode() ,Python3 中是 str(Pyhon3 对文本数据进行了整合,默认为 Unicode 文本数据)
    • six.binary_type,二进制数据的类型。Python2中是 str,Python3 中是 bytes
    • six.MAXSIZE, list 或 dict 等容器的最大尺寸。这相当于 Python 2.6 及更高版本(包括3.x)的 sys.maxsize。在 Python3 中没有直接的等价物, 因为它的整数类型的长度仅受限于内存大小

    使用示例:

    import six
    
    def dispatch_types(value):
        if isinstance(value, six.integer_types):
            handle_integer(value)
        elif isinstance(value, six.class_types):
            handle_class(value)
        elif isinstance(value, six.string_types):
            handle_string(value)
    

    3.2 模块位置兼容

    Python3 重新组织了很多模块的位置,例如 Python2 的 HTMLParser,在 Python3 中是 html.parser。

    可以使用 six 导入,兼容模块导入:

    from six.moves import html_parser
    

    在大多数情况下,six.moves 别名是 Python3 中模块的名称。

    这里 ,你可以看到一个 Supported renames 名单。

    其他 其他的内容可以在官方的文档找到,基本上就是通过six来调用,而不是自己对Python判断。包括:

    3.3 其他

    除了上面的兼容性操作,six 还提供了:

    • 二进制和文本数据的兼容
    • uniittest assert的兼容
    • urllib 库改动的兼容
    • 高级的自定义move

    4. 参考