过去几年,Python 3 的采用量明显增加,但它仍有很长的路要走。采用 Python 的大型公司倾向于在其基础架构上运行大量的 Python 2.7 代码,Facebook 也不例外。在今年的 PyCon 2018 会议上,Facebook 产品工程师 Jason Fried 讲述了该公司在过去四年时间里,Python 3 从几乎无人问津到成为该公司主流 Python 版本的全过程,也展示出 Fried 作为一名工程师的坚持。
演讲视频: https://www.youtube.com/watch?v=H4SS9yVWJYA
Jason Fried 现任 Facebook 的产品工程师,在帮助公司实现这一目标方面发挥了重要作用,他在演讲中讨论了关于如何解决 Python 版本迁移的一些想法。
Fried 在 2011 年进入 Facebook 工作,很快,他就发现需要自学 Python,因为在 Facebook,Python 代码更容易通过代码评审。后来,他发现自己成为推动 Facebook 采用 Python 3 的主要动力。他表示从未特地进行过计划,只是 Python 用得多了,自然而然产生的结果。
(Jason Fried)
Jason Fried 最初因在 Python 内部社区中非常活跃而展露头角,他经常是第一个站出来回答问题的人。随后,他在 Facebook 作为 Python 的支持者而渐渐成名(或者说”臭名昭著“),因为当他看到 Python 代码中出现问题时,他会未经许可就直接上手修改。这在 Facebook 行之有效,因为这里并没有真正意义上的自上而下的控制机制,每个人都有权利对一个代码变更做出修改,就像你有权利做出代码变更一样。随着时间推移,他在 Facebook 的内部 Python 社区内建立起了威信,这对他日后在 Facebook 顺利主导 Python 版本迁移起到了很大的推动作用。
这是 Fried 演讲中提到的关于 Python 3 在 Facebook 从无人问津到占主导地位的完整时间线,可以看到,这个过程花了将近 5 年的时间,实属不易。
2013 年(基本支持→负面情绪→希望乍现)
Python 3 永远不可能出现在 Facebook
Python 3 在 Facebook 的落地过程非常艰难,一开始遭到内部的否定,甚至让 Fried 一度认为它不可能出现在 Facebook,直到目前超过 55% 的采用率,整个过程非常坎坷。
他说,要在“Facebook 规模”上改变 Python 版本这类东西需要花费相当多的时间,并需要使用很多“外交“手段。他讲述了他和几个工程师是如何利用空闲时间,在没有任何权力的情况下让 Python 3 成为 Facebook 主要版本的。
2013 年,Facebook 打算开始初步支持 Python 3,因为他们需要向构建系统中添加 Python 3 支持。但因为 Facebook 库不支持 Python 3,所以无法向构建系统添加 Python3。而如果构建系统不支持 Python 3,Facebook 库就不可能支持 Python 3。这就像《第二十二条军规》里描述的矛盾军规一样,Python 3 虽然“可用”,但在 Facebook 环境中得不到任何支持。
另外,在 2013 年,Facebook 内部对 Python 3 抱有很大的消极情绪。总体来说,他们认为公司的编程语言将永远停留在 Python 2.7 版本。还有人建议完全换成另一种语言。Fried 也曾表示(在内部社区中)Python 3 永远不会出现在 Facebook。只有一个人向他提出质疑,并建议他做些事情来改变这种情况,虽然当时他忽略了这个建议,但这个想法却留在了他的脑海里。
希望乍现
2013 年,事情出现了转机。当年一月,当时 Facebook 正在使用的“linter”工具需要从 __future__ 导入 print_function、division、absolute_imports 和 unicode_literals,以延长 Python 2 代码库的使用寿命。他们在任何 linter 提示的地方导入这些包,这样可以更容易将模块转为 Python 3。
用于序列化和远程过程调用的 Apache Thrift 框架在 Facebook“无处不在”。由于它仅支持 Python 2,所以成为最大的障碍。但是,由 Facebook Thrift 团队发起的一个有关 Thrift 新特性的问卷调查显示,开发者普遍希望能够添加 Python 3 支持。Fried 投了赞成票,但并不是跟风,他认为 Python 2 接口需要重构,因为它看起来好像 Java。
当他看到 Guido van Rossum 在旧金山的 Yelp 谈论一个叫做“Tulip”(最终成为了 asyncio 模块)的东西时,他的想法开始转变。他一直是 Python 异步编程爱好者,但因为框架(例如 Twisted、gevent)之间的差异而变得碎片化。而 Tulip 让异步 I/O 操作之间可以互操作。在那次演讲结束之前,他与 Facebook Thrift 团队沟通,表示 Thrift 应该直接支持 Tulip,而不是等 Twisted、gevent 和其他框架迁移到 Python 3。几天后,Thrift 团队发布了一个路线图,其中就有对 Python 3 和 Tulip 的支持。
Thrift 团队在 2014 年初推出了这两项新特性,但此后六个月并没有什么动静。用户并没有对此作出反应,实际上他们不关心,甚至根本不知道已经发生了这些变更。Fried 还顺便引用了中国盖了房子却没人住的例子来说明这种情况,真是让人哭笑不得。
2014 年(改变文化→从头开始→强制推行)
新项目
2014 年 8 月,他开始重写一个服务,并计划使用 gevent 和 Python 2,但他后来才意识到,如果这么做的话,在完成这个项目时它就过时了。为了有所改变,需要有人成为第一个做出改变的人。要在 Facebook 推动使用 Python 3,那个人非 Fried 莫属。
于是他使用 Python 3 开始他的项目,可想而知,他面对的是一个”一塌糊涂“的局面。当时 Facebook 没有人用 Python 3,构建系统不支持他的代码,而且所有第三方包仅适用于 Python 2。在他修复了所有问题,让代码通过编译后,又在运行时出了问题。
为了让代码能够正常运行,他必须修复所有问题。他重新构建了数百个第三方包,这样它们就可以同时支持两个版本的 Python,而且他必须让所有内部库可以兼容 Python 2 和 Python 3。但是,每天都有人会将 Python 2 变更提交到他的依赖项中。他需要不停地修复问题,并对此感到厌倦。一种解决方案是在组织内部强制进行 Python 3 合规,但这在 Facebook 根本不可能。但是,如果你表现得好像有某种权力时,人们会渐渐相信你真的有这种权力。
他动用了很多关系把 Pyflakes(一个 lint 工具)添加到构建过程中。他能够证明添加它是有道理的,因为虽然已经有了 PEP 8,但 Pyflakes 可以解决其他额外的代码质量问题。此外,Pyflakes 几乎没有误报,所以它不会惹火开发人员。他做了一些设置,让 Pyflakes 能够扫描所有需要审查的代码,先是 Python 2,然后是 Python 3。这有助于将 Python 3 兼容性扩展至所有开发人员,而不仅仅是他自己,这让他的项目取得了进展。
在刚开始,他必须花费大量的时间向人们解释“linter 是没有错的”,并且让代码能够在 Python 3 上运行是有价值的。如果开发人员开始觉得迁移到 Python 3 是件困难的事,他们就会回到“让我们永远留在 Python 2”的心态。他要尽量保证开发人员能够顺利在 Python 3 上运行代码。
2015 年(培训)
培训
虽然克服了一些困难,但在 Facebook 扩大 Python 3 地盘的进展甚微或毫无进展。他加入了为 Facebook 新员工进行 Python 编程培训的团队。他希望兼容代码仅用于遗留项目,而新项目应该用 Python 3 开发。
2015 年,他修改了新员工 Python 培训内容,表示 Facebook 总有一天会转向 Python 3,只编写 Python 2 代码是没有意义的,因为未来得重写。他教导新员工,所有代码都应该与 Facebook 基础架构和构建系统一致,如果不是,他们应该提交错误或尝试自行修复。这样,新的员工开始在工作中使用 Python 3,这就是进步的开始。“奇怪的是,事情就这么发生了”。
2015 年 1 月,他终于交付了他的项目。他花了大半年的时间告诉人们它有多好,为什么他们应该尽可能地使用 Python 3。一年来,很多在 Facebook 致力于推行 Python 3 的盟友在公司中出了名。
2016 年(Python 3 成为默认编程语言)
其中一位盟友是Łukasz Langa,他“说服了 Instagram 转向 Python 3”。 2016 年,Fried 和 Langa 在 Facebook 组建了一支全新的团队,在公司内部培训 Python,他们称之为“滑稽漫步团”( The Ministry of Silly Walks )。虽然只有两个人,但毕竟是一个“Python 团队”,于是他之前提到的“权威”开始起作用了:人们认为他们可以在 Facebook 做出有关 Python 的决策。
2016 年,他发现 Python 3 的采用量增长虽然缓慢,但还是有稳步的增长。人们在会议上提到它,他还经常听到有新项目在使用它。即使 Python 3 不是默认设置,项目也会选择使用它,Facebook 此时对 Python 3 的看法已经发生了变化。2016 年 5 月,Fried 表示打算将构建系统切换到默认使用 Python 3,他的这一提议几乎得到了绝对支持。几天之后,他完成了切换,切换之后并没有带来任何不良影响。
Fried 表示,2016 年,在 Facebook 中推动 Python 3 项目的只有十个人,其中三个是主要推动者,而且人事流动不断,做这个项目的很多人都是兼职。
2016 年底,有一个项目团队发表了一篇文章,其中介绍了切换到 Python 3 的结果。开发人员从 Python 2 换到 Python 3 时只需做出一些修复,运行代码的速度就提高了 40%,并仅使用了一半的内存。这打破了 Fried 之前听到的一个传言:Python 3 比 Python 2 慢。早期版本的 Python 3 可能是这样,但现在肯定不是,他说道。
2017 年(Instagram 迁移)
好事情发生
2017 年初,Facebook 因为 Instagram 完成了 Python 3 迁移而感受到 Python 3 迁移带来的荣光。Python 版本升级原来并不可怕,反而带来了可用的新功能。Facebook 开发人员现在开始使用新的静态类型或使用 asyncio 改造旧服务。“Python 在 Facebook 又开始变得很有趣了”。
现在的问题是,每个人都在问什么时候可以停止支持 Python 2。当 Python 2 支持库或模块出现回归时,通常会听到开发人员询问是否可以直接升级到 Python 3。而几年前,情况是完全相反的。“哦,世界真美好啊!”
2018 年(Python 3 占比超过 55%)
他展示了一张 Facebook 的 Python 服务入口端点随时间变化的图表,从 2015 年第三季度开始,那个时候只有四个 Python 3 服务入口端点。截至 2016 年年中,当切换到默认使用 Python 3 时,Facebook 已经有 4%的服务入口端点使用了 Python 3。2018 年 3 月,这一比例超过 50%。5 月中旬,当他发表演讲时,运行 Python 3 的 Facebook 服务入口端点比例已达 55%。在 Facebook,只能在 Python 2 上运行的代码现在处于尴尬的境地,Fried 说道。
Łukasz Langa 发推文,对 Python 3 低 CPU 占用和运行速度提升表示赞赏。
演讲接近尾声,他对演讲做了概述。总的来说,他的建议包括:
- 你要做的是创新,做出改变,结果自然会来;
- 你必须通过“亲力亲为让人看到你想要的变化”来引导开发者;
- 你还应该寻求他人的帮助,不要单枪匹马;
- 另外,培训新员工去实现你未来的目标是很重要的。
- 收集需要的数据;
- 享受得到的成果,用 Python 3 写一些“非常棒的东西”。
最后,他还回答了观众提出的一些问题。有人问,如何在传统、等级分明的组织中实现演讲中所说的目标。Fried 认为,实际上这可能会更容易一些,因为你不需要说服成千上万的开发者,只需要让管理层意识到这件事情的好处就可以了。如果在文化保守的组织中,这也可能很难,但专注于代码质量改进可能对此有所帮助。另一个问题是关于整体代码,而不是多个入口点,对于这个问题,Fried 建议看看 PyCon 2017 上的 Instagram 主题演讲 [YouTube 视频 https://www.youtube.com/watch?v=66XoCk79kjM ]。
整个演讲让人受益匪浅,包括 Fried 强调的倡导者和领导者,以及坚持不懈的精神在一个项目中的的重要性。
查看英文原文: https://lwn.net/SubscriberLink/758159/f1f631e1535ab9d6/
感谢无明对本文的审校。
评论 1 条评论