Python 3 的开发和分发面临的挑战

9
假设我已经开发了一个通用的终端用户实用程序,用Python编写。以前,我只有一个可用版本适用于Python 2.3或更高版本。只需要说“如果需要,请下载Python,然后运行此脚本”。在源代码控制中只有一个版本的脚本(我正在使用Git)来跟踪。
随着Python 3的推出,这不再是必须的。在可预见的未来,我将需要同时开发两个不同的版本,一个适用于Python 2.x,另一个适用于Python 3.x。从开发角度来看,我可以考虑以下几个选项:
1. 在同一分支中维护两个不同的脚本,并同时对两者进行改进。 2. 维护两个独立的分支,并在开发过程中来回合并共同的更改。 3. 只维护一个版本的脚本,并检入一个可以将脚本从一个版本转换为另一个版本的补丁文件。当足够多的更改已经被做出,使得补丁无法干净地应用时,解决冲突并创建一个新的补丁。
目前我倾向于选择第三种选项,因为前两种会涉及到很多容易出错的琐碎工作。但是第三个选项似乎有些混乱,我的源代码控制系统应该为我管理补丁。
对于分发包装,可以选择更多的选项:
1. 提供两个不同的下载包,一个适用于Python 2,另一个适用于Python 3(用户必须知道为其使用的Python版本下载正确的包)。 2. 提供一个下载包,其中包含两个不同的脚本(然后用户必须知道运行正确的那个)。 3. 一个下载包含两个特定版本的脚本,并且具有一个小型存根加载程序,可以在两个Python版本中运行,并运行安装的Python版本的正确脚本。
再次强调,目前我倾向于第三种选项,尽管我还没有尝试开发这样的存根加载程序。
是否有其他想法?
5个回答

9

编辑:我的原始答案是基于2009年的情况,当时Python 2.6和3.0是当前版本。现在,随着Python 2.7和3.3的推出,有其他选择。特别是,现在使用单个代码库来支持Python 2和Python 3是完全可行的。

请参见将Python 2代码移植到Python 3

原始答案:

官方建议是这样说的:

将现有的Python 2.5或2.6源代码移植到Python 3.0,最好的策略如下: 1.(前提条件:)从优秀的测试覆盖率开始。 2.将其移植到Python 2.6。这应该不会比从Python 2.x移植到Python 2.(x+1)更费力。确保所有测试都通过。 3.(仍在使用2.6:)打开-3命令行开关。这将启用有关将在3.0中删除(或更改)的功能的警告。再次运行测试套件,并修复您收到警告的代码,直到没有警告并且所有测试仍然通过为止。 4.在源代码树上运行2to3源到源翻译器。(有关此工具的更多信息,请参见2to3-自动Python 2到3代码转换。)在Python 3.0下运行转换结果。手动解决任何剩余的问题,修复问题,直到所有测试再次通过。 不建议尝试编写可以在Python 2.6和3.0下无需更改就能运行的源代码;您必须使用非常扭曲的编码风格,例如避免打印语句、元类等等。如果您正在维护需要支持Python 2.6和Python 3.0的库,则最佳方法是通过编辑源代码的2.6版本并再次运行2to3翻译器来修改第3步,而不是编辑源代码的3.0版本。
理想情况下,您将得到一个兼容2.6并可使用2to3转换为3.0的单个版本。实际上,您可能无法完全实现这个目标。因此,您可能需要一些手动修改才能使其在3.0下运行。
我会在分支中维护这些修改,就像您的选项2一样。但是,与其在该分支中维护最终的3.0兼容版本,我会考虑在2to3翻译之前应用手动修改,并将这个修改后的2.6代码放入您的分支中。这种方法的优点是,该分支与2.6主干之间的差异相对较小,只包括手动更改,而不是2to3所做的更改。这样,分支应该更易于维护和合并,并且您应该能够从未来的2to3改进中受益。
或者,采取一种“等待和观察”的方法。只使用单个2.6版本加上2to3翻译尽可能进行移植,并将剩余的手动修改推迟到您真正需要3.0版本时再进行。也许到那时,您不再需要任何手动调整...

+1 这是官方推荐,也是我认为最合理的选择。 - Carl Meyer
听起来你引用的官方建议的最后一句适用于我的情况。尽可能利用2to3是有道理的,直到2.x代码完全被弃用为止。 - Greg Hewgill
1
单一代码库的做法不再被反对。DjangoPyramid采用了这种方法,我相信还有其他很多框架也是如此。事实上,这似乎是目前最流行的做法。 - tshepang
@Tshepang:感谢提醒。我已经更新了我的帖子,提示它不再是最新的,并添加了当前指南的链接。 - oefe

2

对于开发而言,选项3过于繁琐。维护两个分支是最简单的方法,尽管在不同的版本控制系统中实现方式会有所不同。许多分布式版本控制系统将更喜欢使用单独的存储库(具有共同的祖先以帮助合并),而集中式版本控制系统可能更容易使用两个分支。选项1也是可行的,但在我的看法中,您可能会错过一些要合并的内容,而且稍微容易出错。

对于分发,如果可能的话,我也会使用选项3。无论如何,这三个选项都是有效的,我已经见过这些模型的变化。


2

我认为这条路不是一个好选择。无论从哪个角度看,都是痛苦的。除非有强烈的商业利益要同时保留两个版本,否则这只会带来更多的麻烦而不是收益。

我认为现在最明智的做法是继续开发2.x,至少几个月,甚至一年。在某个时刻,宣布2.x的最终稳定版本,并开始为3.x+开发下一个版本。

例如,我不会转向3.x,直到一些重要的框架也使用3.x:PyQt、matplotlib、numpy等等。如果他们在某个时候停止对2.x的支持并开始为3.x开发,我也不介意,因为我知道很快我也能转向3.x。


1

我建议首先迁移到2.6版本,这个版本非常接近Python 3.0。你甚至可以等待2.7版本发布,它将更接近Python 3.0。

然后,一旦你迁移到了2.6(或2.7),我建议你只保留一个脚本版本,在必要的地方使用类似"if PY3K:... else:..."的语句。当然,这不是我们开发者喜欢编写的代码,但这样你就不必担心管理多个脚本、分支、补丁或发行版,这将是一场噩梦。

无论你选择什么方式,请确保进行全面的测试,覆盖到100%的代码。

祝你好运!


根据http://python.org/download/releases/3.0/,Python 3.0是“一个新的生产就绪版本”。在最终发布之前,“Python 3000”是旧名称。 - Greg Hewgill
由于“print”语句语法的差异,不能简单地使用“if PY3K”语句来选择版本。这就是为什么这是一个棘手的问题。 - Greg Hewgill
嗨,Greg。我同意你的第一个评论并相应地修复了我的答案,谢谢。至于你的第二个评论,我认为我们可以解决类似的问题。对于打印功能,您可以使用“from future import print_function”(它将在2.6中添加打印功能,并且在3.0中是无操作)。 - MiniQuark

0
无论选择哪种开发选项,通过彻底的单元测试可以缓解大多数潜在问题,以确保两个版本产生匹配的输出。 话虽如此,对我来说,选项2似乎最自然:从一个源代码树应用更改到另一个源代码树是(大多数)版本控制系统设计的任务 - 为什么不利用它们提供的工具来简化这个过程。
对于开发而言,很难在不了解“你的受众”的情况下做出判断。强大的Python用户可能会欣赏不必下载两份软件副本,但对于更普通的用户群体,它应该“只需运行即可”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接