Supporting Python 3(支持python3)——迁移策略

迁移策略

制作一个向后不兼容的软件版本是有很高风险的。 当人们需要重写他们的软件或者为了支持两个语言或框架的版本维护割裂的版本时,风险就是没有完成过度并且一直停留在老版本,或者更糟糕是他们切换到基本的框架。

出于这个原因Python 的2.6和2.7版本为能同时运行在Python 2和Python 3都包含向前兼容,以及使用2to3(一个能够把代码从Python 2转换成Python 3程序和包)的形式迁移。还有其他一些你可以用的技术和策略,也有一些使用2to3的不同方式。其中使用的策略很大程度上取决于你要转换的软件的类型。

仅支持Python 3

当你在同一时间只支持一个Python的版本是最简单的情况。在这种情况下,你可以仅仅转换你的代码到Python 3并且忘掉Python 2。使用这种策略,你首先要用2to3来自动转换大部分的变化,然后修复在Python 3代码中依旧存在的问题。你也可能想要通过转换所有代码并清理它的方式,因为在你的情况下2to3转换可能并不总是最好的解决办法。

Python 2和Python 3的单独分支

如果你需要继续支持Python 2,最简单的情况是在你的源代码中有一个Python 2的分支及另一个Python 3的分支。然后你必须在两个分支中做每一天变化,这多了一些工作,但是如果代码不是经常变动的话这是可行的。

用这个策略的一个问题是你的分发变得复杂了,因为你现在有两个发布版本了并且你需要确保Python 3和Python 2的用户获取各种的版本。解决这个的办法在分发包 的文档上。

使用2to3转换到Python 3

在复杂的情况下,你可以使用在Python 2保持源代码并用2to3把它转换成Python 3的做法同时支持Python 2和Python 3。 那意味着每一次代码改变时你都将必须都运行2to3以便你可以在Python 3下测试它,但在另一方面2to3了处理许多的不同之处。

做这些你需要一个执行2to3转换的脚本,因为通常做些所有的步骤很快就变得非常无聊。因为每次你做了一些修改时都需要做这个转换以便在Python 3下测试,或许你想要仅在修改过的文件上运行转换因为转换过程可能会相当慢。那意味着转换脚本需要比较文件的时间戳来找到哪些文件被修改了并仅仅转换它们,也就意味着这个脚本不可能是一个简单的shell脚本。

你当然可以自己写这些脚本,但或许你可能不需要这么做。如果你在使用Distutils,它已经支持把执行2to3作为构建过程的一部分。这也解决了分发问题,因为这种方式你可以仅发布Python 2的代码,当被安装在Python 3时2to3将会在代码安装时运行。 这样,你不需要弄独立的包甚至在你的包里弄两个副本。 分发包 上也有关于这个的信息。

然而,懒惰的程序员这里的做法应该是用Distribute,因为它包含一些2to3-story的扩展。

使用Distribute来支持2to3转换

Distribute[1] 是Phillip J. Eby的流行的Setuptools包的一个分支并且它提供了Python 3的兼容,以及扩展了简化的对相同来源Python 2和Python 3的支持。基本上Distribute所做是扩展Distutils创建_py_2to3命令的规则及集成2to3到打包经过的所有部分。

在2013年这些修改将会合并加Setuptools,但是在写Setuptools的时候是不支持Python 3的。

使用Distribute你可以在setup.py中添加一些额外的参数使得2to3在构建时进行转换。这意味着你只需要在版本控制系统中拥有一个版本,因些你只需要修正一次错误。你也只需要一个发布的代码,所以你只需要发布软件一将你并且只有一个包要下载安装在Python 2和Python 3。

你仍然需要在你想要支持的Python版本下运行你的测试,但是Distribute包含一个在测试前能用2to3你的代码的命令。用那个 你可以很容易地建立包。然后测试变成为每一个你想要支持的Python版本你仅仅需要运行一次python setup.py test 。

用种解决方案的主要缺点是不能使用更早版本的2to3,因为他们太傻了。在实践中,这意味着你必须要目标机器上安装Python 3.1或者之后的版本。这一般不会有问题,因为支持Python 3的大多数平台已经使用Python 3.1的支持了。

你可以在使用Distribute支持多版本Python及标准Distribute文档[2]下找到如何为你的Python 3支持建立你的模块或者包。

无需转换支持Python 2 和 Python 3

在许多情况下,修改代码使其在Python 2和Python 3无需转换就能运行是完全可行的,但是你需要一些技巧来避免Python 2和Python 3之间的不兼容问题。

Python 2.6 和 2.7有很多向前兼容,使得支持Python 2.6和Python 3比Python 2.5和Python 3更容易。支持2.5或者更老的版本,意味着你必须使用更多的技巧。Python 3.3还重新为字符串引入了u""常量,它有助于解决支持Python 3的主要困难之一。

Benjamin Petersons的six模块[3]也是使用封闭不兼容的方式来提供帮助的,并且由于对旧版本Python支持的需求正在减少,同时支持Python 2和Python 3已经成为首选的方式。

还有一些你不能使用Distribute或者不想使用的情况存在。你也可能需要在一个因为不能使用Distutils安装因而不能使用Distribute的规范下分发代码。在这些情况下你不能使用Distribute的2to3支持,然后使用2to3要花更多的时间,这样不用2to3是一个更有吸引力的前景。

即使你使用2to3将你的项目作为一个整个,你仍然可能最终要写一些代码使其能在不转换地在Python 2和Python 3下运行。这对于引导脚本和安装脚本或者从字符串中生成的代码(例如:创建命令行脚本)是很有用的。 你当然可以根据不同的Python版本使用不同的字符串,甚至使用lib2to3来在字符串上运行2to3。但是在这种情况,成生的代码通常不通过2to3在所有Python版本运行是更容易的。

如果你想要不用2to3来支持Python 3,我的建议是对代码运行一次2to3然后修复代码到能在Python 3下工作。只有到那时再在需要的地方使用six引入Python 2支持到Python 3代码。首先添加Python 2.7的支持,然后是Python 2.6。这样做,有时候会是一个非常快速无痛的过程。

还有一个叫作python-modemize的工具可以做对你的代码做2to3类型转换,但是它会用six库保留Python 2兼容。这会是一个好的开始。

更多做这些必须技术的信息在不用2to3转换支持Python 2 和3 章节中。

使用3to2

3to2工具是可以用写“固定济”的方式灵活地定义变化。在这里几乎任何类型的Python代码转换都是可想而知的并且3to2[4]是一个Joe Amenta写的用于从Python 3转换成Python 2的固定济集合。 这个工具允许你用Python 3写代码,然后在发布前转换成Python 2。

但是,没有Distribute支持3to2,还有Python2.5及更早的版本不包含所需的lib2to3包。因此目前仍是一个有趣的实验,不过在将来这可能改变。

 哪种策略适合你?

应用

你也许并不需要支持旧版本的Python,除非你的代码是一个重复使用的包或框架,除非当其他人要求你支持Python 3时你的客户停留在Python 2。在多大数情况你完全可以丢弃Python 2的支持。

Python模块和包

如果你正在开发某一种其他Python开发都使用的包或者模块,你可能需要同时支持Python 2和Python 3。大多数你的用用户在即将到来的一段时间城会用Python 2,所以你想要给他们新的功能。但是如果你不支持Python 3,Python 3的用户一定会寻找其他的包来满足他们的需求。

如果从功能角度来看包是稳定的,在你的版本控制系统中有两个独立的分支并在它们上做bug修复是完全合理的。但是如果你的包正在积极的开发中,你可能想要用相同的代码库同时支持Python 2和Python 3。你想要使用官方的2to3转换方法还是偿试不需要转换步骤直接在同时在Python 2和Python 3下运行,这取决于你的代码用来做什么及你需要支持什么版本的Python。

在有些情况下,你不得不花很多精力在使用相同代码在Python 2和Python 3下执行,因为太难了。也有一些情况下,代码通过执行2to3是如此简单,甚至几乎不用修改代码。大多数代码都是介于两之间,因此做决定不总是容易的。 一个好主意是在你的代码上执行2to3并查看不同之处。 如果2to3在你的代码中产生了大量的变化,那么你可能想要使用它转换代码以尽量绕路的数量。

如果你可以只支持Python2.6或者之后的版本,那么不使用2to3转换支持Python 3可能是最好的选项。 特别是在你没有二进制/Unicode切换的影响或者只想支持Python 3.3或者之后版本的情况下。

如果你已经使用Distutils或者其衍生出的Setuptools和Distribute发布你的包,那么使用Distribute的2to3支持是很容易的并且可能是阻力最小的路径。你也可以用个方式开始并点点滴地修改代码以达到不修改转换的目的。

框架

使用框架的益处不仅在于框架的自身的发展,也在于框架的插件及可用的扩展。因此使框架对所有开发者都容易使用和扩展框架到Python 3是很重要的,否则你可以会被久远卡在Python 2里。

如果你的框架是用使用Distutils,、Setuptools或者Distribute作为打包系统的包扩展的,这意味着你的框架的用户已经处在很好的位置,因为他们可以用Distutils或者Distribute来做2to3转换以达到同时支持框架的旧新版本。

如果扩展是用除Distutils外的其他方式打包和发布的,你可能要考虑写自己的支持脚本集来让转换更容易或者停止支持旧版本,以便你的第三包开发者不需要使用2to3。

结论

一般情况下,如果写的是终端用户软件,你可以马上切换到Python 3,使用对你的代码执行一次2to3来开始切换。如果你写的是一个Python包,你需要同时支持Python 2和Python 3,你可以放弃Python 2.5的支持并且首先偿试不用转换支持Python 2和3。

如果你需要支持Python 2.5或者更新版本,那么使用2to3常常是最好的选项。

附注:

[1]http://pypi.python.org/pypi/distribute
[2]http://packages.python.org/distribute/python3.html
[3]http://pypi.python.org/pypi/six
[4]http://pypi.python.org/pypi/3to2


在湖闻樟注:

原文http://python3porting.com/preparing.html

引导页Supporting Python 3:(支持Python3):深入指南

目录Supporting Python 3(支持Python 3)——目录


转载于:https://my.oschina.net/soarwilldo/blog/504185

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值