返回介绍

13.3 使用six

发布于 2024-01-23 21:41:45 字数 2439 浏览 0 评论 0 收藏 0

正如我们所看到的,Python 3破坏了与早期版本间的兼容性并且周边很多东西发生了变化。但是,这门语言的基础并没有发生变化,所以是可以实现一种转换层的,也就是一个能实现向前和向后兼容的模块——Python 2和Python 3之间的桥梁。

这样的模块是有的,名字就叫做six(http://pythonhosted.org/six/),因为2乘以3等于6。

six首先要做的就是提供一个名为six.PY3的变量。它是一个布尔值,用来表明是否正在运行Python 3。对于任何有两个版本(Python 2和Python 3)的代码库而言这都是一个关键变量。不过在用的时候要谨慎,如果代码中到处都是if six.PY3,那么后续会很难维护。

正如在8.1节中所讨论的,Python 3有一个非常好的功能能够返回可迭代对象而不是列表。这意味着类似dict.iteritems这样的方法将会消失,并且dict.items将返回一个迭代器而不是列表。显然,这会破坏你的代码。six对此提供了six.iteritems,使得所有要做的只是将

for k, v in mydict.iteritems():
  print(k, v)

替换为

import six

for k, v in six.iteritems(mydict):
  print(k, v)

看,Python 3的兼容性立刻就解决了!six提供了大量类似的辅助函数以提升不同版本间的兼容性。

raise语法在Python 3中也发生了变化4,因此再次抛出异常应该使用six.reraise。

如果正在使用元类,Python 3对其进行了彻底修改。six针对这个转换有一个不错的技巧。例如,如果正在使用abc抽象基类元类,则可以像下面这样使用six:

import abc
from six import with_metaclass

class MyClass(with_metaclass(abc.ABCMeta, object)):
  pass

谈到Python 3必然会涉及其引入的字符串和Unicode混乱问题。在Python 2中,字符串的基本类型是str,其只能用来处理ASCII码字符串。而后来加入的unicode类型,则用来处理文本的真正字符串。在Python 3中,基本的类型仍然是str,但它共享了Python 2中unicode类的属性,并能处理更为高级的编码。bytes类型代替str类型,用来处理基本的字符流。

six提供了一组不错的函数和常量用来处理这种转换,如six.u和six.string_types。同样对整数也提供了相应的兼容性,通过six.integer_types能够处理在Python 3中移除的long类型。

如同在13.1节中讨论的,有些模块已经变动了,因此six提供了一个不错的名为six.moves的模块,用来透明地处理这些变动。

例如,在Python 3中ConfigParser模块被重命名为configparser。因此,在Python 2中使用ConfigParser的代码:

from ConfigParser import ConfigParser

conf = ConfigParser()

就可以修改成下面的方式以兼容主要的Python版本:

from six.moves.configparser import ConfigParser

conf = ConfigParser()

提示

也可以通过six.add_move添加自己的变动来处理其他转换。

six库可能不足以覆盖你的所有用例。在这种情况下,构建一个封装了six的兼容模块是值得的。通过在一个特殊的模块中隔离这个,可以确保未来有能力针对Python的后续版本做一些增强,或者在你不再需要继续支持某个特定Python版本的时候销毁(部分的)它。six是开源的,因此你可以直接贡献它而不用维护自己的兼容模块。

最后需要提及的是modernize模块(https://pypi.python.org/pypi/modernize)。它是在2to3之上的一层很薄的包装器,用来通过迁移代码到Python 3使其“现代化”。但是不同于单纯转换语法为Python 3代码,它使用six模块。与标准的2to3工具相比,它是更好的选择,通过执行大多数繁重的工作使你的移植工作有个良好的开端。还是值得试试的。

1我已经听说过有这样的项目存在。

2u前缀在Python 3.0中被移除了,但在Python 3.3中又被加了回来,参考PEP 414(https://www.python.org/dev/peps/pep-0414/)。

3另一个不支持老版本的原因。

4现在只接受一个参数,一个异常。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文