堅持的力量:Facebook向Python3遷移的過程回顧

坚持的力量:Facebook向Python3迁移的过程回顾

Python3的使用量在過去幾年有了明顯增加,但它仍有很長的路要走。使用Python的大公司傾向於在其基礎架構上運行Python2.7代碼,Facebook也不例外。在PyCon2018大會上,Facebook的工程師賈森‧弗裡德講述了該公司在過去四年左右的時間裡,Python3從幾乎無人問津到成為該公司主流Python版本的全過程。他在幫助公司實現這一目標中發揮了重要作用,他的演講(視頻地址:https://www.youtube.com/watch?v=H4SS9yVWJYA)為其他公司如何遷移Python版本提供了一些思路。

弗裡德2011年進入Facebook,工作不久,他就意識到必須得自學Python,因為Python寫的代碼更容易通過代碼評審。後來,他發現自己成了推動Facebook使用Python3的主要動力。他說從未刻意計劃過,只是因為Python用得多了自然產生的結果。

坚持的力量:Facebook向Python3迁移的过程回顾

賈森‧弗裡德

賈森‧弗裡德最初在內部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/
譯者:錢利鵬


分享到:


相關文章: