如何将 Python 2 代码移植到 Python 3

介绍

Python是在20世纪80年代后期开发的,并于1991年首次发布的。由英国喜剧组 Monty Python 创作的名称,Python 被设想为 imperative general-purpose ABC 编程语言的继任者,在其第一次迭代中,Python 已经包括了例外处理, 函数,和 类与继承

本教程将指导您从 Python 2 到 Python 3 迁移代码的最佳实践和考虑,以及您是否应该保持与两种版本兼容的代码。

背景

Python 2 于 2000 年发布,标志着一个更加透明和包容的语言开发过程,它包含了更多的编程功能,并在整个开发过程中增加了更多的功能。

Python 3被认为是Python的未来,是目前正在开发的语言版本。Python 3于2008年底发布,解决并修改了内在的设计缺陷。

Python 2.7 于 2010 年作为 2.x 版本的最后一个版本发布, Python 2.7 背后的意图是让 Python 2.x 用户通过提供两者之间的某些兼容性来更容易地将功能移至 Python 3。

您可以了解更多关于Python版本的信息,并通过阅读我们的教程`Python 2 vs Python 3: Practical Considerations来选择使用哪个版本。

开始使用Python 2.7

要移动到Python 3,或同时支持Python 2和Python 3,您应该确保您的Python 2代码完全兼容Python 2.7。

许多开发人员已经专门使用了Python 2.7代码,但重要的是要确认,任何只支持早期版本的内容都与Python 2.7正常工作,并且与Python 2.7风格一致。

确保您的代码在Python 2.7中是特别重要的,因为它是唯一的Python 2版本,目前仍在维护并收到bugfixes。

此外,一些让您更容易端口代码的工具,例如寻找编程错误的 Pylint包,不支持早于 2.7 的 Python 版本。

重要的是要记住,虽然Python 2.7目前仍在支持和维护,但它最终将迎来其终止寿命 PEP 373详细介绍Python 2.7的发布时间表,并在写作时将其日落日期标记为2020年。

测试覆盖

创建测试案例可以是将Python 2迁移到Python 3代码的工作的重要组成部分,如果您正在维护Python的多个版本,您还应该确保您的测试套件总体覆盖范围良好,以确保每个版本仍然按预期运行。

作为测试的一部分,您可以将交互式Python案例添加到您所有函数、方法、类和模块的文本中,然后使用内置的 doctest 模块来验证它们的运行情况。

除了「doctest」之外,您还可以使用「coverage.py」包(https://pypi.python.org/pypi/coverage)来跟踪单元测试覆盖,此工具将监控您的程序,并记住代码的哪些部分已经执行,哪些部分可能已经执行,但没有执行。

请记住,您不是寻求100%的测试覆盖范围,您希望确保覆盖任何令人困惑或不寻常的代码。

了解Python 2和Python 3之间的区别

了解Python 2和Python 3之间的差异将确保您能够利用Python 3中可用的或将可用的新功能。

我们的Python 2 vs Python 3](https://andsky.com/tech/tutorials/python-2-vs-python-3-practical-considerations-2)指南概述了两种版本之间的一些关键差异(https://andsky.com/tech/tutorials/python-2-vs-python-3-practical-considerations-2#key-differences),您可以查看官方的Python文档(https://docs.python.org/3/)以获取更多细节。

当您开始使用端口和迁移时,您现在可以执行几个语法更改。

《印刷》

Python 2 的_ print statement 已更改为 Python 3 中的 print() _function。

Python 2 Python 3


打印你好,世界!```打印(你好,世界!)``

《exec》

Python 2 的_ exec 声明已更改为允许在 Python 3 中明确的本地和全球的函数。

Python 2 Python 3


exec 代码ahul exec(代码) exec 代码在全球ahul exec(代码,全球) exec 代码在 (全球,本地)ahul exec(代码,全球,本地)

````和``

Python 2 使用 / 操作员,Python 3 引入 // _for floor division。

Python 2Python 3
5 / 2 = 25 / 2 = 2.5
5 // 2 = 2

要在Python 2中使用这些运算符,从__future__模块中导入(https://andsky.com/tech/tutorials/how-to-import-modules-in-python-3)`分区`:

1from __future__ import division

閱讀更多關於 分別與整數

升起

在Python 3中,用参数提取例外需要,而 strings不能用作例外。

Python 2Python 3
raise Exception, argsraise Exception
raise Exception(args)
raise Exception, args, tracebackraise Exception(args).with_traceback(traceback)
raise "Error"raise Exception("Error")

除外

在Python 2中,很难列出多个例外,但在Python 3中这种情况发生了变化。

请注意,在Python 3中,_ as 被用在_ except 中。

Python 2 Python 3


除例外,变量: 除例外作为变量: 除例外(OneException, TwoException)作为变量:

《def》

在Python 2中,函数可以采用如 tupleslists等序列。

Python 2 Python 3


def 函数(arg1, (x, y)): def 函数(arg1, x_y): x, y = x_y

《expr》

Python 2 的 backtick 语法不再存在 使用_ repr() 或_ str.format() 在 Python 3._

Python 2 Python 3


x = 355/113′′```x = repr(355/113)`:

String 格式化

string 格式语法已从 Python 2 更改为 Python 3.

Python 2Python 3
"%d %s" % (i, s)"{} {}".format(i, s)
"%d/%d=%f" % (355, 113, 355/113)"{:d}/{:d}={:f}".format(355, 113, 355/113)

学习如何在Python 中使用字符串格式(https://andsky.com/tech/tutorials/how-to-use-string-formatters-in-python-3)。

班级

没有必要在 Python 3 中声明_ object

《Python 2》

1class MyClass(object):
2    pass

《Python 3》

1class MyClass:
2    pass

在Python 3中,元类被设置为_ 元类 _ 关键字。

《Python 2》

1class MyClass:
2    __metaclass__ = MyMeta
1class MyClass(MyBase):
2    __metaclass__ = MyMeta

《Python 3》

1class MyClass(metaclass=type):
2    pass
1class MyClass(MyBase, metaclass=MyMeta): 
2    pass

更新代码

您可以使用两种主要工具来自动更新您的代码到Python 3,同时保持与Python 2兼容性: **未来**和 现代化. 这些工具的每一个行为略有不同:未来的工作使Python 3语句和最佳实践存在于Python 2,而现代化旨在使用Python `六’模块来提高兼容性的Python 2/3子集。

使用这些工具来处理代码重写的细节可以帮助您识别和纠正潜在问题和模糊。

您可以通过您的 unittest 套件运行该工具,以视觉检查和验证代码,并确保所做的自动修订是准确的。

从这里开始,你可能需要做一些手动修订,特别是针对在上面的部分中提到的Python 2和Python 3之间的变化(https://andsky.com/tech/tutorials/how-to-port-python-2-to-python-3#learn-about-differences-between-python-2-and-python-3)。

利用未来,你应该考虑在你的Python 2.7模块中添加这个导入陈述:

1from __future__ import print_function, division, absolute_imports, unicode_literals

虽然这也将导致重写,但它将确保您的Python 2代码与Python 3语法一致。

最后,您可以使用 pylint来识别代码中的任何其他潜在问题. 该包包含数百个单独的规则,涵盖可能出现的各种问题,包括 PEP 8 风格指南规则,以及使用错误。

您可能会发现,您的代码中有一些构件可能会混淆pylint和用于自动迁移的工具. 如果您无法简化这些构件,则需要使用全面的单元测试案例。

持续一体化

如果你打算为多个Python版本维护你的代码,你需要尽可能频繁地在代码上运行和重新运行你的Unittest套件,通过连续集成(而不是手动)。

如果您在 Python 2 和 3 兼容性维护中使用了 six,则需要使用多个环境进行测试。

您可能考虑使用的环境管理工具之一是 tox,因为它将检查您的包安装在不同的Python版本中,在每个环境中运行测试,并作为连续集成服务器的前端。

结论

重要的是要记住,随着越来越多的开发人员和社区关注Python 3,该语言将变得更加精细和符合程序员不断变化的需求,并且对Python 2.7的支持将减少。

值得一看的是将Python 2转移到Python 3的项目,包括案例研究,例如(Python 3转移到Python 3)。

Published At
Categories with 技术
comments powered by Disqus