介绍
Python是在20世纪80年代后期开发的,并于1991年首次出版。以英国喜剧团体Monty Python为灵感的名字,Python被认为是命令式通用ABC编程语言的继承者。 在第一次迭代中,Python已经包含异常处理,函数和继承类。
本教程将指导您将代码从Python 2迁移到Python 3时做出的最佳做法和注意事项,以及是否应保持与两个版本兼容的代码。
背景
Python 2于2000年发布,表明了更加透明和包容性的语言开发过程。 它包括更多的程序化功能,并在整个开发过程中增加了更多功能。
Python 3被视为Python的未来,是目前正在开发的语言版本。 发布于2008年底,Python 3解决和修改了内在设计缺陷。 然而,Python 3的采用一直很慢,因为语言不能向后兼容Python 2。
Python 2.7作为最新的2.x版本在2010年发布。 Python 2.7背后的意图是通过提供两者之间的兼容性,使Python 2.x用户更容易将功能移植到Python 3。
您可以通过阅读我们的教程“ Python 2与Python 3:实际注意事项 ”,了解有关Python版本的更多信息,并选择使用哪些版本
https://docs.python.org/3/howto/pyporting.html
从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。 如果您正在使用较早版本的Python 2,则必须解决您遇到的不再受支持且不再接收buxfix的代码的问题。
此外,一些使您更容易使用端口代码的工具,例如Pylint软件包查找编程错误,不支持早于2.7的Python版本。
重要的是要记住,尽管Python 2.7目前仍然得到支持和维护,但它最终将会达到生命的终结。 PEP 373详细介绍了Python 2.7发布时间表,在撰写本文时,将其日期作为2020年。
测试范围
创建测试用例可能是将Python 2转换为Python 3代码所做的工作的重要部分。 如果您正在维护多个版本的Python,那么您还应确保测试套件的整体覆盖率很好,以确保每个版本仍然按预期工作。
作为测试的一部分,您可以将交互式Python案例添加到所有函数,方法,类和模块的文档中,然后使用内置的doctest
模块来验证它们是否正常工作。
除了doctest
,您可以使用coverage.py
包来跟踪单元测试范围。 该工具将监视您的程序并注意代码的哪些部分已被执行,哪些部分可能已被执行,但是没有。 coverage.py
可以将报告打印到命令行或提供HTML输出。 它通常用于测量测试的有效性,显示您通过测试执行代码的哪些部分,哪些不是。
请记住,您不是针对100%的测试覆盖范围 - 您希望确保覆盖任何令人困惑或不寻常的代码。 为了最佳做法,您应该瞄准80%的覆盖范围。
了解Python 2和Python 3之间的差异3
了解Python 2和Python 3之间的差异将确保您能够利用Python 3中可用或可用的新功能。
我们关于“ Python 2与Python 3 ”的指南涉及两个版本之间的一些主要区别 ,您可以查看官方的Python文档以获取更多详细信息。
开始移植和迁移时,您可以实现几种语法更改。
print
Python 2 的 print
语句已经 在Python 3 中更改为 print()
函数。
Python 2 | Python 3 |
---|---|
print "Hello, World!" |
print("Hello, World!") |
exec
Python 2 的 exec
语句已经更改为允许Python 3中的显式本地和全局变量的函数。
Python 2 | Python 3 |
---|---|
exec code |
exec(code) |
exec code in globals |
exec(code, globals) |
exec code in (globals, locals) |
exec(代码,全局变量,本地人) |
/
和//
Python 2使用 /
操作符 进行分区 ,Python 3引入 //
用于分区。
Python 2 | Python 3 |
---|---|
5 / 2 = 2 |
5 / 2 = 2.5 |
5 // 2 = 2 |
要在Python 2中使用这些运算符,请从__future__
模块导入division
:
from __future__ import division
阅读更多关于整数的划分 。
raise
在Python 3中,使用参数引发异常需要括号,字符串不能用作异常。
Python 2 | Python 3 |
---|---|
raise Exception, args |
raise Exception |
raise Exception(args) |
|
raise Exception, args, traceback |
raise Exception(args).with_traceback(traceback) |
raise "Error" |
raise Exception("Error") |
except
在Python 2中,很难列出多个异常,但在Python 3中已经发生了变化。请注意, except
在Python 3 中明确使用 。
Python 2 | Python 3 |
---|---|
except Exception, variable: |
except AnException as variable: |
except (OneException, TwoException) as variable: |
def
在Python 2中,函数可以采用诸如元组或列表的顺序。 在Python 3中,这个拆包已被删除。
Python 2 | Python 3 |
---|---|
def function(arg1, (x, y)): |
def function(arg1, x_y): x, y = x_y |
expr
Python 2的反驳语法不再存在。 在Python 3中 使用 repr()
或 str.format()
。
Python 2 | Python 3 |
---|---|
x = `355/113` |
x = repr(355/113): |
字符串格式化
字符串格式化语法已从Python 2更改为Python 3。
Python 2 | Python 3 |
---|---|
"%d %s" % (i, s) |
"{} {}".format(i, s) |
"%d/%d=%f" % (355, 113, 355/113) |
"{:d}/[:d}={:f}".format(355, 113, 355/113) |
class
在Python 3中 不需要声明 object
。
Python 2
class MyClass(object):
pass
Python 3
class MyClass:
pass
在Python 3中,元类用 metaclass
关键字 设置 。
Python 2
class MyClass:
__metaclass__ = MyMeta
class MyClass(MyBase):
__metaclass__ = MyMeta
Python 3
class MyClass(metaclass=type):
pass
class MyClass(MyBase, metaclass=MyMeta):
pass
更新代码
您可以使用两个主要工具来自动将代码更新为Python 3,同时保持与Python 2 兼容 : 未来和现代化 。 每个这些工具的行为都有所不同:Python 2中存在Python 3成语和最佳实践的future
工作,而modernize
的Python 2/3子集使用Python six
模块来提高兼容性。
使用这些工具来处理重写代码的细节可以帮助您识别和纠正潜在的问题和模糊。
您可以通过单元测试套件运行该工具来目视检查和验证代码,并确保所做的自动修订是准确的。 一旦测试通过,您可以转换代码。
从这里,您可能需要进行一些手动修订, 特别是针对上一节中提到的Python 2和3之间的更改 。
利用future
,您应该考虑将此import
语句添加到每个Python 2.7模块中:
from __future__ import print_function, division, absolute_imports, unicode_literals
虽然这也将导致重写,它将确保您的Python 2代码与Python 3语法一致。
最后,您可以使用pylint
软件包来识别代码中的任何其他潜在问题。 该包包含数百个单独的规则,涵盖可能发生的广泛问题,包括PEP 8风格指南规则以及使用错误。
您可能会发现代码中有一些构造可能会混淆pylint
和用于自动迁移的工具。 如果您不能简化这些构造,则需要使用彻底的单元测试案例。
持续整合
如果要维护多个版本的Python代码,您需要保持警惕,通过持续集成(而不是手动),在开发代码时尽可能多地运行并重新运行单元测试套件。 。
如果您使用six
软件包作为Python 2和3兼容性维护的一部分,则需要使用多个环境进行测试。
您可以考虑使用的一种环境管理工具是tox
软件包 ,因为它将使用不同的Python版本来检查软件包安装,在每个环境中运行测试,并充当连续集成服务器的前端。
结论
重要的是要记住,随着更多的开发人员和社区关注焦点在Python 3上,该语言将变得更加完善,符合程序员不断变化的需求,并且不再支持Python 2.7。 如果您决定维护Python 2和Python 3代码库的版本,则可能会对前者造成困难,因为随着时间的推移可以减少错误修复。
值得一看的是将Python 2移植到Python 3的项目,包括将 chadeet移植到Python 3中的案例研究。