9

假设我开发了一个用 Python 编写的通用最终用户实用程序。以前,我只有一个适用于 Python 的版本,该版本晚于 2.3 版左右。说“如果需要,请下载 Python,然后运行此脚本”就足够了。源代码控制中只有一个版本的脚本(我正在使用 Git)来跟踪。

在 Python 3 中,这不再是必然的。在可预见的未来,我需要同时开发两个不同的版本,一个适合 Python 2.x,一个适合 Python 3.x。从开发的角度来看,我可以想到几个选择:

  1. 在同一分支中维护两个不同的脚本,同时对两者进行改进。
  2. 维护两个独立的分支,并随着开发的进行来回合并常见的更改。
  3. 只维护脚本的一个版本,并签入将脚本从一个版本转换为另一个版本的补丁文件。当进行了足够多的更改以致补丁不再干净应用时,请解决冲突并创建新补丁。

我目前倾向于选项 3,因为前两个将涉及很多容易出错的乏味。但是选项 3 似乎很混乱,我的源代码控制系统应该为我管理补丁。

对于配送包装,有更多选项可供选择:

  1. 提供两种不同的下载包,一种适用于 Python 2,一种适用于 Python 3(用户必须知道为他们拥有的任何 Python 版本下载正确的下载包)。
  2. 提供一个下载包,其中包含两个不同的脚本(然后用户必须知道运行正确的脚本)。
  3. 一个包含两个特定于版本的脚本的下载包,以及一个可以在两个 Python 版本中运行的小型存根加载程序,它为已安装的 Python 版本运行正确的脚本。

我现在再次倾向于选项 3,尽管我还没有尝试开发这样的存根加载器。

还有其他想法吗?

4

5 回答 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 的未来改进中受益。

Alternatively, take a bit of a "wait and see" approach. Proceed with your porting only so far as you can go with a single 2.6 version plus 2to3 translation, and postpone the remaining manual modification until you really need a 3.0 version. Maybe by this time, you don't need any manual tweaks anymore...

于 2009-01-18T20:38:22.897 回答
2

对于开发来说,选项 3 过于繁琐。维护两个分支是最简单的方法,尽管不同 VCS 的方法会有所不同。许多 DVCS 会更喜欢单独的存储库(具有共同的祖先来帮助合并),而集中式 VCS 可能更容易与两个分支一起使用。选项 1 是可能的,但您可能会错过一些要合并的东西,而且 IMO 更容易出错。

对于分发,如果可能的话,我也会使用选项 3。无论如何,所有 3 个选项都是有效的,我不时看到这些模型的变化。

于 2009-01-18T19:06:36.403 回答
2

我不认为我会走这条路。无论你怎么看都是痛苦的。真的,除非同时保持两个版本有强烈的商业利益,否则这比收益更令人头疼。

我认为现在继续为 2.x 开发更有意义,至少几个月,最多一年。在某个时间点,正是时候宣布 2.x 的最终稳定版本并为 3.x+ 开发下一个版本

例如,在一些主要框架采用这种方式之前,我不会切换到 3.x:PyQt、matplotlib、numpy 和其他一些。而且我真的不介意他们是否会停止对 2.x 的支持并开始为 3.x 开发,因为我知道在很短的时间内我也可以切换到 3.x。

于 2009-01-18T20:31:32.550 回答
1

我将从迁移到非常接近 python 3.0 的 2.6 开始。你甚至可能想要等待 2.7,它会更接近于 python 3.0。

然后,一旦你迁移到 2.6(或 2.7),我建议你只保留一个版本的脚本,在它会出现的少数地方写上“if PY3K:... else:...”之类的东西强制的。当然,这不是我们开发人员喜欢编写的那种代码,但是您不必担心管理多个脚本或分支或补丁或发行版,这将是一场噩梦。

无论您选择什么,请确保您拥有 100% 代码覆盖率的全面测试。

祝你好运!

于 2009-01-18T19:44:26.640 回答
0

无论选择哪种开发选项,大多数潜在问题都可以通过彻底的单元测试来缓解,以确保两个版本产生匹配的输出。也就是说,选项 2 对我来说似乎是最自然的:将更改从一个源代码树应用到另一个源代码树是(大多数)版本控制系统设计的任务——为什么不利用它们提供的工具来缓解这个问题。

对于发展,如果不“了解你的受众”就很难说。Power Python 用户可能会很高兴不必为更一般的用户群下载您的软件的两个副本,它可能应该“正常工作”。

于 2009-01-18T19:37:11.520 回答