写点什么

为什么迁移至 Python 3 这么难?

2020 年 3 月 24 日

为什么迁移至Python 3这么难?

2020 年 1 月 1 日,Python 2 的生命周期正式截止,Python 核心开发人员也宣布即将不再提供该版本的安全更新,并建议用户尽快迁移至 Python 3。然而问题也在此时出现了,不论 Python 3 有多少优点,迁移的过程对于用户来说都极其痛苦,但是如果不这么做的话,又会有其他问题出现。对此,开发者只剩一声长叹,难啊!


迁移至 Python 3,用户怨声载道

2020 年 3 月 4 日,一位用户在 Twitter 上吐槽:



他的大概意思是:“每个人都坚持要摆脱 Python 2,但这样的做法却将我们拥有的所有功能完善且有用的 Python 2 代码从资产变成负债。”


随后他又举例说:



“自 2011 年用 Python 2 编写以来,我的 milter 实现一直是完全稳定的。现在,我不得不破坏它的稳定性,因为 Python 2 没法用了。”


有同样感受的人不只是他一个,尤其是那些大公司的开发人员。


2013 年,Facebook计划将代码迁移至Python 3,但是从产生这个想法到真正交付,一共花费了四年的时间,代码迁移仅仅是难题的开始,更重要的是让自己的员工使用并适应 Python 3;另有 LinkedIn 进行的“旷日持久战”,550 个代码存储库(库、应用程序和服务)要迁移、上百万行的代码要处理,还有内部用于持续集成/持续交付(CI/CD)框架、命令行接口以及部署和数据科学工具,这种散乱的非整体式环境用 Warsaw 的话来说“包括数百种独立的微服务和工具,外加几十个支持库”。


如此浩瀚的工程,花费的时间、精力都是巨大的,参与其中的人怨声载道,甚至有人将其称之为“噩梦般的工作”。然而当庞大的迁移终于完成,新的问题又出现了。


跨平台的分布式版本控制软件 Mercurial 就是 Python 编写的,所以对于向 Python 3 的迁移,Mercurial 也是非常的积极。在经历了同样大规模的迁移后,问题暴露了出来,负责 Mercurial 运维工作的工程师 Gregory Szorc 在博客上进行了一番吐槽:


简而言之,我将 Mercurial 和其他项目移植到 Python 3 的经验极大地破坏了我对 Python 的好印象。从语言到热情的社区,我一直以来都对 Python 充满爱,但我仍在努力理解 Python 如何通过选择他们所做的过渡计划来设法给社区带来如此多的困难。



Python 3.0 于 2008 年 12 月 3 日发布,社区花了十年的时间来接受它。这应该被普遍认为是失败的。



我真的对 Python 很不满意。移植到 Python 3 所需的工作量惊人。对于 Mercurial 而言,Python 3 引入了很多问题,但并不能解决很多问题。我们在泥泞中摸爬滚打了好几年,直到最终陷入比我们开始时更糟的状态。我敢肯定,几年后它将变得更好。但是在此之前,我们要经历 5 年以上的过渡期。官方宣称 Python 3 过渡会对项目造成破坏和干扰,这是一种太轻描淡写的说法。


问题出在哪里?

Python 3 的迁移为什么如此困难?回答这个问题之前,我们先简单了解一下它诞生的背景。


自 2008 年发布以来,Python 2.0 已经走过了十多个年头。它的最后一次重大更新 ——Python 2.7 是在 2010 年。


虽然 Python 2.x 是一个还不错的版本,但同时也带来了相当大的历史包袱,例如,它有两种整数类型;存在恼人的 Unicode 编码问题;它混淆了懒惰和渴望的功能工具;它有一个标准的库,但加载内存非常庞大;它自诩的强类型,却有偶尔令人啼笑皆非的运算结果 None < 3 < “2”。总的来说,它的一些“阴暗角落“,包含了 Python 1 时代太多的历史包袱。


由于修复这些问题可能会破坏现有代码,而几乎所有为 2.0 编写的代码仍可在 2.7 上运行,Python 3 应运而生。



设计之初,Python 3 的预期是用户会直接转移到新版本,从而放弃使用 Python 2 。然而在一开始,人们有很多理由不采用 Python 3:最主要的原因是,它并没有与 Python 2 兼容。同时,大多数的库希望同时在 Python 2 和 Python 3 上运行,这在一开始很难运作,并且由于缺乏支持工具,移植代码的工作十分艰难。


转折点发生在大约 2016 年左右的 Python 3.5 发行版中 ,该版本增加了矩阵乘法、引入了 asyncio、对 OrderedDict 的速度进行了提升以及实现了类型提示,这些提示为 Python 带来了一些类似于静态语言的功能。


更高版本包含更多功能,例如 Pathlib 库和 f 字符串操作。 通过这些更改,人们使用的许多库(例如用于机器学习的 scikit-learn )开始向 Python 3 迁移。


除了 Python 3 本身存在的一些技术问题,用户不愿意迁移的主要原因还有这样几点:


安全问题。 具有讽刺意味的是,用户会认为不进行升级会带来更大的风险,但是在大型组织或机构中,不允许员工自己升级 Python:管理员或安全团队会向他们推送更新。 在某些情况下,也不允许下载 PIP。 如果 Python 2 是安全团队同意的默认设置,那么它可能需要做出巨大的努力才能说服人们将其切换到 3,尤其是在受到严格监管(例如医疗保健或金融)和政府的环境中。


使用惯性。 尽管许多版本的 Linux 中(例如 RHEL),都同时兼容 Python 2 与 Python 3,但这不是默认的选项,因此用户在 2 和 3 之间切换时,经常发现一些错误,尤其是指向系统版本的指针,例如,在 Debian 上使用 Python。


如何避免迁移出现问题?

如何迁移到 Python 3?每家公司的做法可能有所不同,所以在此之前,不如先看看官方给出的建议。


Python 软件基金会已经为需要同时运行 Python 2 和 3 的组织提供了如何实现跨代兼容性的综合指南,以下是其建议的摘要:


1.放弃对 Python 2.6 和更早版本的支持,因为从 Python 2.7 迁移要容易得多,并且如果必须运行 Python 2.6,请考虑使用 six library 来与 Python 3 兼容。


2.确保 setup.py 文件正确指定了代码库支持的 Python 版本,并且该文件至少包括 Programming Language :: Python :: 2 ::仅作为 trove 分类器。


3.测试套件应至少具有 80%的代码覆盖率,即在测试过程中执行多少源代码的名称。如果不了解代码覆盖率,请使用coverage.py提供的工具。


4.阅读Python的“新增功能”文档和免费的“ 移植到Python 3”手册,了解 Python 2 和 Python 3 之间的区别。


5.使用FuturizeModernize使 Python 2 代码与 Python 3 兼容,请确保阅读文档,以便解决这些无法处理的问题。


6.确保适应在 Python 2 和 3 之间处理整数除法的更改。例如,在 Python 2 中 9/2 = 4,而在 Python 3 中 9/2 = 4.5。如果可以在代码中使用“future import”除法和“//”运算符进行整数除法,那么代码已经与 Python 3 兼容。


7.Python 3 更改了可以与 str 类型一起使用的数据,以使文本和二进制数据之间的区别更加清晰。不幸的是,对于同时处理文本和二进制数据的代码,必须执行以下步骤以确保代码符合要求:


https://docs.python.org/3/howto/pyporting.html#text-versus-binary-data


8.当运行的代码因运行的版本不同而表现不同时,最好检查 Python 3 支持的特定功能是否能够运行,而不是检查 sys.version_info [0]是否等于 3。


9.为了帮助对齐用 Python 3 编写的任何新代码并确保其兼容性,请在创建的任何新模块的顶部使用以下语句:from future import absolute_import, from future import division, 以及 from future import print_function。


10.使用 caniusepython3 提供的工具,检查哪些软件依赖项会阻止支持 Python 3 。


11.迁移代码后,请在 setup.py 文件中更新分类器,使其包含 Programming Language :: Python :: 3,以表明代码支持 Python 2 和 3。


12.通过使用tox自动化测试并将此设置与持续集成系统进行集成,以确保代码与 Python 2 和 3 保持兼容。


另外,为了将 Python 2 迁移到 Python 3 代码,NCSC 还建议使用2to3应用程序,该应用程序将尝试自动执行该过程。


总而言之,虽然很麻烦,但是为了保持功能的先进性,企业或个人开发者还是不得不选择迁移到 Python 3。如果想避免迁移过程出现问题,可以参考一些大公司的迁移情况,这里有一些案例可供参考,希望可以帮到广大开发者:



2020 年 3 月 24 日 14:303182
用户头像
陈思 InfoQ编辑

发布了 575 篇内容, 共 203.6 次阅读, 收获喜欢 1180 次。

关注

评论

发布
暂无评论
发现更多内容

账户经常被盗号怎么办?防盗“黑科技”了解一下

华为云开发者社区

华为云 云安全 主机安全 双因子认证 弱密码

USDT承兑商系统开发,USDT支付系统软件搭建

13530558032

XSKY S3 Console 为对象存储系统赋能

XSKY融合存储

Week11

丿淡忘

针对目前在线教育存在问题的解决方案

anyRTC开发者

WebRTC 在线教育 直播 安卓

调度选得好,下班回家早

易观大数据

OFD 版式技术解析系列(四):OFD文档解析流程

华宇法律科技

版式文档 OFD

架构师0期Week11作业1

Nan Jiang

Lambda架构已死,去ETL化的IOTA才是未来

易观大数据

架构训练营第十一周作业

张锐

熔断、限流的一些理解

elfkingw

架构师0期Week11作业2

Nan Jiang

深圳数字货币交易所开发商,币币撮合交易软件开发

13530558032

IDEA插件之Mybatis Log plugin破解!!!

不才陈某

Java idea插件

java安全编码指南之:基础篇

力软.net/java开发平台

高可用注意点

dony.zhang

高可用 高可用系统的架构 高可用系统的运维

作为程序员,推荐5种编程语言!

代码制造者

Python 编程语言 低代码 C语言 零代码

合约跟单APP开发模式,合约跟单系统源码搭建

13530558032

程序员不得不知的软技能

架构精进之路

软技能

一款JAVA快速开发平台,多项目整合,给开发提提速

力软.net/java开发平台

「Java 25周年」 工具软件 平台应用服务

源码解析 | 万字长文详解 Flink 中的 CopyOnWriteStateTable

Apache Flink

flink

安全及高可用策略

Lane

极客大学架构师训练营

解码微盟半年财报:同比增长59.9%,SaaS商业版图不断扩大

ToB行业头条

SaaS 微盟

力扣1514——概率最大的路径

健健

算法 最短路径

架构训练营第十一周感悟

张锐

Grabana:使用 Golang 或 Yaml 生成 Grafana Dashboard

郭旭东

go golang Grafana

30万奖金等你拿!Apache Flink 极客挑战赛入门指南(附Demo)

Apache Flink

flink

一个用户秘密加密验证功能

elfkingw

知乎李大海与阿里云贾扬清联合直播,AI大咖眼中的行业前景

InfoQ_967a83c6d0d7

区块链钱包系统开发服务商,区块链钱包应用搭建

13530558032

java 是什么?作用是什么?

InfoQ_34a83d636158

为什么迁移至Python 3这么难?-InfoQ