来源:Python程序员
ID:pythonbuluo
Python3的使用量在过去几年有了明显增加,但它仍有很长的路要走。使用Python的大公司倾向于在其基础架构上运行Python2.7代码,Facebook也不例外。在PyCon2018大会上,Facebook的工程师贾森‧弗里德讲述了该公司在过去四年左右的时间里,Python3从几乎无人问津到成为该公司主流Python版本的全过程。他在帮助公司实现这一目标中发挥了重要作用,他的演讲(视频地址:https://www.youtube.com/watch?v=H4SS9yVWJYA)为其他公司如何迁移Python版本提供了一些思路。
弗里德2011年进入Facebook,工作不久,他就意识到必须得自学Python,因为Python写的代码更容易通过代码评审。后来,他发现自己成了推动Facebook使用Python3的主要动力。他说从未刻意计划过,只是因为Python用得多了自然产生的结果。
贾森‧弗里德
贾森‧弗里德最初在内部Python社区中非常活跃,他经常是第一个站出来解决问题的人。最终他在Facebook成了有名的(或者说“臭名昭著的”)Python程序员,因为当他看到别人的Python代码有问题时,他会不经许可直接修改。这在Facebook行之有效,因为这里并没有真正意义上自上而下的控制机制,每个人都有权利修改代码。随着时间推移,他修改的代码越来越多,在公司内部的Python社区建立起了威信,这对他日后主导Python版本的迁移起到了很大作用。
他说,要在“整个Facebook公司层面”上改变Python版本需要相当长的时间,还需要使用很多“外交”手段。他讲述了他和几个工程师利用空闲时间,在没有任何权力主导的情况下让Python3成为了Facebook的主要Python版本。
2013年,在Facebook内Python3.3得到了初步的支持。这是向构建系统添加Python3支持的一部分。但是这个任务因Facebook库不支持Python3被阻止,而如果构建系统不支持Python3,Facebook库就不可能支持Python3。这就像《第22条军规》里描述的矛盾军规一样,Python3虽然“可用”,但在Facebook 的环境中得不到任何支持。
另外,2013年时Facebook内部还有很多人对Python3抱有消极情绪。大部分人认为公司将永远停留在Python2.7版本上。还有人建议完全换成另一种语言。弗里德也曾表示(在内部社区中)Python3永远不会出现在Facebook。只有一个人向他提出质疑,并建议他做些事情来改变这种情况,虽然当时他忽略了这个建议,但这个想法却留在了他的脑海里。
一线希望
他说,实际上当时还是有一线希望的。2013年1月,当时Facebook正在使用的
lint工具需要从_ future_模块导入四个功能( print_function、division、absolute_imports 和 unicode_literals)以延长Python2代码库的使用寿命。他们在lint工具有提示的地方导入这些包,这样可以更容易将模块转为Python3。
用于序列化和远程过程调用的Apache Thrift框架在Facebook“无处不在”。由于它仅支持 Python2,所以成为Python版本迁移的最大障碍。但是,Thrift团队发起的一个有关Thrift新特性的问卷调查显示,开发者普遍希望能够添加Python3支持。弗里德投了赞成票,但并不是跟风,他认为Python2接口需要重构,因为它看起来好像是用Java编写的。
当他看到吉多•范罗苏姆在旧金山的 Yelp 公司谈论一个叫做“Tulip”(最终成为了 asyncio 模块)的东西时,他的想法开始转变。他一直是Python异步编程的支持者,但总是遇到框架(如 Twisted、gevent)差异而导致的碎片化问题。而Tulip让可以异步 I/O可互操作而不是碎片化。在范罗苏姆的谈话结束之前,他与Thrift 团队沟通,表示Thrift应该直接支持Tulip,而不是等待Twisted、gevent 和其它框架迁移到Python3。几天后,Thrift团队发布了一个路线图,其中就有对Python3和Tulip的支持。
Thrift团队在2014年初推出了这两项新特性,但此后六个月并没有什么动静。用户并没有对此作出反应,实际上他们不关心,甚至根本不知道已经发生了这些变更。
新项目
2014年8月,他开始重写一个服务,并计划使用gevent 和Python2,但他后来才意识到,如果这么做的话,在完成这个项目时它就过时了。为了有所改变,需要有人成为第一个做出改变的人。要在Facebook推动使用Python3,那个人非弗里德莫属。他说,“如果你希望你所在的组织使用Python3,我想起主导作用那个人应该是你。”
于是他使用Python3开始了他的项目,可想而知,他面对的是一个“一塌糊涂”的局面。当时Facebook没有人用Python3,构建系统不支持他的代码,而且所有第三方包仅适用于Python2。当他最终修复了错误允许服务被构建时,又会在运行时失败——在Facebook系统中设置服务入口点的代码报错。
为了让代码能够正常运行,他必须修复所有问题。他重新构建了数百个第三方包,这样它们就可以同时支持两个版本的 Python,而且他必须让所有内部库可以兼容 Python2 和Python3。但是,每天都会有人将仅支持Python2的变更代码提交到他的依赖包中。他厌倦了反复去修复问题。一种解决方案是强制兼容Python3,而这在Facebook根本不可能。但是,如果你表现得好像有某种权威时,人们会渐渐相信你真的有这种权威。
他动用了很多关系把Pyflakes(一个检查代码语法的 lint 工具)添加到构建过程中。他能够证明添加它是有道理的,因为虽然已经有了PEP8标准的lint工具,但Pyflakes 可以解决其他额外的代码质量问题。此外,Pyflakes几乎没有误报,所以它不会惹火开发人员。他做了一些设置,让Pyflakes能够扫描所有需要审查的代码,先是Python2,然后是Python3。这有助于将检查兼容性的工作扩展至所有开发人员,而不仅仅是他自己做这项工作,这让他的项目取得了进展。
在刚开始,他必须花费大量的时间向人们解释“lint工具是没有错的”,并且让代码能够在Python3上运行是有价值的。如果开发人员开始觉得迁移到Python3是件困难的事,他们就会回到“让我们永远留在Python2”的心态。他让开发人员可以轻松地在Python 3环境中运行代码。本来有更轻松的解决方法,那就是“关闭lint工具”,他没有抱怨这一切,只是坚持这样做,所以大多数开发人员开始按他的方法做了。
培训
虽然克服了一些困难,但在Facebook扩大Python3地盘的工作进展甚微或毫无进展。他加入了为Facebook新员工进行Python编程培训的团队。使用lint工具的程序员希望代码能兼容Python2和Python3,但他希望兼容代码仅用于遗留项目,而新项目应该用Python3 开发。他再次亲自动手做出改变:2015 年,他修改了对新员工的Python培训内容,表示Facebook总有一天会转向Python3,只编写Python2代码是没有意义的,因为未来还得重写。他教导新员工,所有代码都应该与Facebook基础架构和构建系统一致,如果不是,他们应该提交错误报告或尝试自行修复。这样,新员工开始在工作中使用Python3,这就是进步的开始。“奇怪的是,事情就这么发生了”。
2015年1月,他终于交付了他的项目。那一年他花了很多的时间告诉人们Python3有多好,为什么他们应该尽可能地使用Python3。一年来,很多和他共同推行Python3的同事在公司中都出了名。
其中一位盟友是尤卡兹·兰加,他“说服了Instagram团队向Python3迁移”。 2016年,弗里德和兰加在Facebook组建了一支全新的团队,在公司内部培训Python,他们称之为“滑稽漫步团”。虽然只有两个人,但毕竟是一个“Python 团队”,于是他之前提到的“权威”开始起作用了:人们认为他们可以在Facebook做出有关Python的决策。
2016年,他发现Python3的使用量增长缓慢但稳定。会议上有人提到它,经常有新项目使用它。即使Python3不是项目的默认选项,Facebook内部此时对Python3的看法也已经发生了变化。2016年5月,弗里德表示要将构建系统的默认Python语言切换到 Python3,他的这一提议几乎得到了绝对支持。几天之后,他完成了切换,切换之后并没有带来任何不良影响。
2016年底,有一个项目团队发表了一篇文章,其中介绍了切换到Python3的结果。开发人员将Python2写的代码换到Python3环境,只是做了一些必要的修复,结果代码的运行速度提高了40%,而且仅用了一半的内存。这打破了弗里德之前听到的一个传言:Python3比Python2慢。早期版本的Python3可能是这样,但现在肯定不是,他说道。
好事情发生
2017年初,因为Instagram完成了向Python3的迁移,Facebook收获了迁移带来的好处。Python版本升级原来并不可怕,反而带来了新的功能。Facebook的开发人员现在可以使用新的静态类型或asyncio等工具。“在Facebook公司使用Python语言又开始变得很有趣了”。
现在的问题是,每个人都在问什么时候可以停止支持Python2。当一个库或模块需要Python2支持时,通常会听到开发人员询问是否可以直接升级到Python3。而几年前,情况是完全相反的。“哦,世界真美好啊!”
他展示了一张Facebook的Python服务入口点随时间变化的图表,从2015年第三季度开始,那个时候只有四个Python3服务入口点。截至2016年年中,当切换到默认使用Python3时,Facebook已经有 4%的服务入口点使用了Python3。2018年3月,这一比例超过50%。5月中旬,当他发表这次演讲时,运行Python3的服务入口点比例已达55%。在Facebook,只能在 Python2上运行的代码现在处于尴尬的境地,弗里德说道。
然后他回顾了这个过程。他说,你不仅仅是去创新;你还必须通过“亲力亲为让人看到你想要的变化”来引导开发者;你应该寻求别人的帮助,即使他们不知道能帮上什么忙,这也是lint工具和单元测试模块率先迁移到Python3的原因。培训新员工去实现你未来的目标是很重要。一旦你到达目标,或者掌握到达目标的方法,要通过享受“好东西”来庆祝:用Python3写一些“很棒的东西”。介绍如何使用新功能会促使其他人也想要使用Python3。
最后,他还回答了观众提出的一些问题。有人问,如何在传统、等级分明的组织中实现演讲中所说的目标。弗里德认为,实际上这可能会更容易一些,因为你不需要说服成千上万的开发者,只需要让管理层意识到这件事情的好处就可以了。如果在文化保守的组织中,这可能很难,但专注于代码质量改进可能对此有所帮助。另一个问题是关于整体代码,而不是多个入口点,对于这个问题,弗里德建议大家看看 PyCon2017上的一个Instagram主题演讲(链接:https://www.youtube.com/watch?v=66XoCk79kjM)。
弗里德的演讲中还提到了很多其他组织可以借鉴的东西,但有一个倡导者和坚韧的领导者非常重要。一家公司要实现这样的改变就得有像弗里德这样的人。
英文原文:https://lwn.net/Articles/758159/ 译者:钱利鹏
*声明:推送内容及图片来源于网络,部分内容会有所改动,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。
- END -