您打算如何处理向 Python 3 的迁移?

Posted

技术标签:

【中文标题】您打算如何处理向 Python 3 的迁移?【英文标题】:How are you planning on handling the migration to Python 3? 【发布时间】:2010-09-15 09:32:48 【问题描述】:

考虑到 Python 3 即将问世,我确信这是大多数 Python 开发人员心中的一个主题。一些让我们朝着正确方向前进的问题:

    您是要同时维护一个 python 2 和 python 3 版本,还是在完成后只拥有一个 python 3 版本?

    您是否已经开始或计划很快开始?还是打算等到最终版本出来再全面展开?

【问题讨论】:

对我们来说,关键是库支持。当我们依赖的库支持 3.0 时,我们会将项目迁移到 3.0。我们不会维护我们软件的 2.x 兼容分支 - 我们会将所有客户的系统升级到 python 3.0。 在 2.5 年后,随着 python 3.2 的发布,现在阅读这个投票率很高的问题和 cmets 的更新会非常有趣。 迁移路径对于库来说仍然很糟糕,因为您不能在同一个文件中同时拥有 2x 代码和 3k 代码。 2to3 适合一次性转换,但作为长期开发选项不可行,因为开发人员不喜欢支持同一源的两个不同版本。一个真正的预处理器会使这个过程更容易,但 python 没有。 @joaquin:这有趣的。我刚刚在一篇关于 2 到 3 兼容性的近期项目博客文章中发布了另一个答案。 【参考方案1】:

这是 Twisted 的总体规划。我本来打算写博客的,但后来我想:既然我能得到 积分,为什么还要写博客呢?

    等到有人关心。

    目前,没有人拥有 Python 3。在至少有一个实际用户站出来说“我需要 Python 3.0 支持”之前,我们不会花费大量精力,并且除了有充分的理由之外事实上 3.0 看起来很闪亮。

    等到我们的依赖项迁移完毕。

    像 Twisted 这样的大型系统有许多依赖项。首先,我们的包括:

    Zope Interface PyCrypto PyOpenSSL pywin32 PyGTK(虽然现在这种依赖关系很轻,但随着迁移的到来,我希望 Twisted 会有更多的 GUI 工具) pyasn1 PyPAM gmpy

    其中一些项目有自己的一系列依赖项,所以我们也必须等待这些。

    等到有人关心帮助

    慈善地,有 5 个人在 Twisted 上工作 - 我说“慈善地”是因为我也算在内,而且我已经好几个月没有承诺了。我们现在有over 1000 open tickets,在花时间把它移植到一个全新的版本之前,如果能真正修复其中的一些——修复错误、添加功能,并通常让 Twisted 本身成为一个更好的产品——那就太好了语言版本。

    这可能包括sponsors 足够关心支付我们的费用,但我希望会有大量关心 3.0 支持并希望帮助推动社区向前发展的志愿者涌入。

    听从 Guido 的建议。

    这意味着 we will not change our API incompatibly,我们将遵循 Guido 去年发布的 transitional development guidelines。首先是进行单元测试,然后在 Twisted 代码库上运行 the 2to3 conversion tool。

    报告 2to3 工具的错误和文件补丁

    当我们实际使用它时,我预计将来运行2to3 会出现很多问题。现在在 Twisted 上运行它需要很长时间,而且(上次我检查过,那是很久以前的事了)无法解析 Twisted 存储库中的一些文件,因此结果输出不会导入。我认为必须有大量来自小型项目的成功案例,并且在该工具真正为我们工作之前进行大量的锤击。

    然而,Python 开发团队在响应我们的错误报告方面非常有帮助,并且对这些问题的早期响应令人鼓舞,因此我希望所有这些问题都能及时得到解决。

    保持 2.x 兼容性数年。

    目前,Twisted 支持 python 2.3 到 2.5。目前,我们正在努力支持 2.6(我们显然必须在 3.0 之前完成!)。我们的计划是根据Ubuntu 的长期支持版本修改我们支持的 Python 版本 - 包含 Python 2.5 的 8.04 版将支持到 2013 年。根据 Guido 的建议,我们将需要放弃对 2.5 的支持为了支持 3.0,但我希望我们能找到解决方法(我们在版本兼容性方面很有创意)。

    因此,我们计划至少在 2013 年之前支持 Python 2.5。两年后,Ubuntu 将发布另一个长期支持的 Ubuntu 版本:如果它们仍然存在,并且按计划进行,那就是 10.04。我个人猜测这将与 Python 2.x,也许是 python 2.8 一起提供,如/usr/bin/python,因为有大量的 Python 软件打包在发行版中,并且需要很长时间才能全部更新。所以,从五年后的 2015 年,我们可以开始考虑放弃对 2.x 的支持。

    在此期间,我们将继续遵循 Guido 关于迁移的建议:在我们的 2.x 代码库上运行 2to3,并修改 2.x 代码库以使其测试在两个版本中都能通过。

    这样做的结果是,直到我 35 岁生日之后,Python 3.x 才会成为 Twisted 的源代码语言——它将成为目标运行时(以及一组准则和限制)对于我的 python 2.x 代码。我希望在未来十年左右使用 Python 2.x 编写程序。

所以,这就是计划。我希望它在一年左右的时间里看起来保守得可笑。 3.x 过渡很容易,每个人都快速升级。其他事情也可能发生:2.x 和 3.x 分支可能会合,有人最终可能会写一个 3to2,或者另一个运行时(想到 PyPy)可能允许运行 2.x 和 3.x 代码直接在同一个过程中,使我们的转换过程更容易。

然而,就目前而言,我们假设,多年来,我们将拥有维护大型代码库的人员(或编写新代码并希望使用其他库的人员尚未迁移)仍然希望在 Twisted 中获得新功能和错误修复的人。很快我希望我们也会有希望在 python 3 上使用 Twisted 的前沿用户。我想尽可能长时间地为所有这些人提供积极的体验。

【讨论】:

1.我代表 Ubuntu 和 Gnome 社区表示,我们都关心、想要和需要在 twisted 中支持 python3。在 Ubuntu 方面,我们不想在 CD 上发布 python2,如果可能的话,将 python2 从 main 移动到 Universe,这样我们就可以减少 python2 解释器的维护和安全工作。 2.可用的 Ubuntu 软件包:python3-zope.interface python3-crypto python3-openssl pygtk via python3-gi object interspection python3-pyasn1 python3-pam 可用上游支持:python-gmpy(支持上游不在 ubuntu 中,我会尽快为你打包) 3.据我所知,在为您寻求帮助方面取得了一些进展。【参考方案2】:

Django 项目使用库 six 来维护可同时在 Python 2 Python 3 (blog post) 上运行的代码库。

six 通过提供一个兼容层来实现这一点,该层智能地将导入和函数重定向到它们各自的位置(以及统一其他不兼容的更改)。

明显优势:

Python 2 和 Python 3 不需要单独的分支 没有转换工具,例如 2to3。

【讨论】:

我与使用 6 将 Django 移植到 python 3 的人 (Aymeric) 交谈:他告诉我这是一项巨大的工作(代码中大约 20% 的行必须修改) ,但是一旦完成,它就完成了,没有维护两个分支并用 2to3 到处乱搞。坦率地说,我认为 Guido 应该改变他的指导方针并结束 2to3 的混乱:每个人使用六个! Django 将在下一个 LTS 版本后放弃 Python2 兼容性:djangoproject.com/weblog/2015/jun/25/roadmap “放弃”听起来像是他们留下了一个坏主意或坏主意。这与事实相去甚远! Django 正在放弃对 Python 2 的支持因为 Python 本身正在放弃对 Python 2 的支持。six 仍然是维护健康、兼容的代码库的最佳方式,但希望在少数情况下不需要它年,因为每个人都将使用 Python 3。【参考方案3】:

2.6 的主要思想是提供到 3.0 的迁移路径。因此,您可以使用from __future__ import X 一次缓慢地迁移一项功能,直到您确定所有功能并可以迁移到 3.0。 3.0 的许多功能也将流入 2.6,因此您可以逐渐缩小语言差距,而不必一次性迁移所有内容。

在工作中,我们计划先从 2.5 升级到 2.6。然后我们开始慢慢启用 3.0 功能,一次一个模块。在某个时候,系统的整个子部分可能会为 3.x 做好准备。

唯一的问题是库。如果一个库永远不会迁移,我们就会被旧库困住。但我非常有信心,我们会在适当的时候为这部分找到一个很好的替代方案。

【讨论】:

【参考方案4】:

作为图书馆作者发言:

我正在等待最终版本的发布。与大多数 Python 社区一样,我的信念是 2.x 将在数周或数月内继续成为主导版本。有足够的时间来发布一个漂亮、完善的 3.x 版本。

我将分别维护 2.x 和 3.x 分支。 2.x 将向后兼容 2.4,所以我不能在 2.6 / 3.0 中使用很多花哨的语法或新功能。相比之下,3.x 分支将使用这些特性中的每一个,从而为用户带来更好的体验。测试套件将被修改,以便 2to3 可以在其上运行,我将为两个分支维护相同的测试。

【讨论】:

> ... 2.x 将在数周或数月内继续成为主导版本,我认为这有点乐观。恕我直言,这将是几年。但我为你的做法喝彩!【参考方案5】:

同时支持

我想为我正在处理的项目尝试将 BeautifulSoup 库转换为 3x,但我可以看到维护两个不同的代码分支是多么痛苦。

目前处理这个问题的模型包括:

    更改 2x 分支 运行 2to3 祈祷它第一次正确地进行转换 运行代码 运行单元测试以验证一切正常 将输出复制到 3x 分支

这个模型有效,但恕我直言,它很烂。对于每次更改/发布,您都必须完成这些步骤 ::sigh::。此外,它不鼓励开发人员使用只能在 py3k 中支持的新功能扩展 3x 分支,因为您本质上仍将所有代码定位到 2x。

解决方案...使用预处理器

因为我找不到一个像样的带有#define 和#ifdef 指令的python 预处理器,所以我写了一个。

它叫pypreprocessor and can be found in the PYPI

基本上,你所做的是:

    导入pypreprocessor 检测脚本在哪个版本的 python 中运行 在预处理器中为版本设置“定义”(例如“python2”或“python3”) 在代码特定于版本的地方添加“#ifdef python2”和“#ifdef python3”指令 运行代码

就是这样。现在它可以在 2x 和 3x 下工作。如果您担心运行预处理器会增加性能损失,还有一种模式可以去除所有元数据并将后处理的源输出到文件中。

最棒的...您只需进行一次 2to3 转换。

这是一个工作示例:

#!/usr/bin/env python
# py2and3.py

import sys
from pypreprocessor import pypreprocessor

#exclude
if sys.version[:3].split('.')[0] == '2':
    pypreprocessor.defines.append('python2')
if sys.version[:3].split('.')[0] == '3':
    pypreprocessor.defines.append('python3')

pypreprocessor.parse()
#endexclude
#ifdef python2
print('You are using Python 2x')
#ifdef python3
print('You are using python 3x')
#else
print('Python version not supported')
#endif

这些是终端中的结果:

python py2and3.py >>>你正在使用 Python 2x python3 py2and3.py >>>你正在使用 python 3x

如果你想输出到一个文件并制作没有额外元数据的干净的特定于版本的源文件,请在 pypreprocessor.parse() 语句之前的某处添加这两行:

pypreprocessor.output = outputFileName.py
pypreprocessor.removeMeta = True

然后:

python py2and3.py

将创建一个名为 outputFileName.py 的文件,该文件是 python 2x 特定的,没有额外的元数据。

python3 py2and3.py

将创建一个名为 outputFileName.py 的文件,该文件是 python 3x 特定的,没有额外的元数据。

有关文档和更多示例,请查看pypreprocessor on GoogleCode。

我真诚地希望这会有所帮助。我喜欢用 python 编写代码,我希望尽快看到支持进展到 3x 领域。我讨厌看到语言没有进步。尤其是,由于 3x 版本解决了许多特色 WTF,并使语法看起来对从其他语言迁移的用户更友好。

此时的文档是完整的,但并不详尽。我会尽快为 wiki 提供一些更广泛的信息。

更新:

虽然我专门设计了 pypreprocessor 来解决这个问题,但它不起作用,因为词法分析器会在执行任何代码之前对所有代码进行语法检查。

如果 python 有真正的 C 预处理器指令支持,它将允许开发人员在同一个文件中同时编写 python2x 和 python3k 代码,但由于 C 预处理器的坏名声(滥用宏替换来更改语言关键字)我看不到合法的 C 预处理器支持很快就会添加到 python 中。

【讨论】:

【参考方案6】:

Zope 工具包在支持 Python 3 方面进展缓慢。慢主要是因为许多这些库非常复杂。

对于大多数库,我使用 2to3。一些库不需要它,因为它们很简单,或者大部分代码都在 C 扩展中。 zc.buildout 是一个相关的包,将在没有 2to3 的情况下运行相同的代码以支持 Python 2 和 3。

我们将 ZTK 移植到 Python 3,因为许多其他库和框架都依赖于它,例如 Twisted 和 Pyramid 框架。

【讨论】:

【参考方案7】:

我的一些更复杂的 2.x 代码将保持在 2.5 或 2.6。 一旦我经常使用的一些 3rd 方库更新为 3,我将转向 3.0 进行所有新开发。

【讨论】:

以上是关于您打算如何处理向 Python 3 的迁移?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确处理猫鼬模式迁移?

如何正确处理猫鼬模式迁移?

如何正确处理猫鼬模式迁移?

如何处理 Django 中未应用的迁移?

在 Python 3 中使用 sys.stdin 进行文本处理时,我应该如何处理 BOM?

如何处理无效的先前有效的 Flyway 迁移