亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

手把手教你將一個舊的大型項目遷移到 Python 3

發布時間:2020-07-14 10:28:25 來源:網絡 閱讀:285 作者:Python小咖 欄目:編程語言

一年半前,我們就決定使用 Python 3 了。我們已經討論了很長時間,現在是時候使用了!現在這個過程已經結束了,我們已經把生產環境的最后部署都遷移到了 Python 3

  • 整個代碼庫大約有 240 k 行,不包括空行和注解。

  • 這是一個基于 Web 的批處理任務系統。并且只有一個生產,部署環境。

  • 代碼庫大約有 15 年的歷史了。

  • 雖然這是一個 Django 應用程序,但部分代碼是先于 Django 公布之前寫的。

關于修改 Python 3 的一些基本統計數據,是基于對 git 提交歷史的粗略過濾產生的:

  • 275 次提交

  • 4080 次添加代碼行

  • 3432 次刪除代碼行

我發現有 109 個 jira 問題與這個項目相關。

Py2 → six → py3

我們的理念一直是 py2 ?py2/py3 ? py3 因為我們實在無法在實際生產中實現巨變,這種直覺也以令人驚訝的方式被證明是正確的。這意味著 2 到 3 是不可能的,我認為這很常見。我們嘗試過使用 2 to 3 來檢測 Python 3 的兼容性問題,但很快這也被發現無法成立。基本上,這樣的更改意味著在 Python 2 中的代碼將被破壞。這樣的改變不可行。

結論是使用 six, 這是一個庫,可以方便的構建一個在 Python 2 和 3 中都有效的代碼庫。

首當其沖的就是更新之前的依賴關系。這項工作需要立刻啟動,因為之后會有更多的內容要更新。

現代化

Python-modernize 是我們選擇進行遷移的工具。它是一個可以自動將 Py 2 代碼庫轉換為可兼容 six 代碼庫的工具。我們首先引入一個測試,作為 CI 的一部分,來檢查基于 modernize 的新代碼是否已經準備好兼容 py3 了。這樣做最大的效果的是讓那些仍使用 Py 2 語法的人意識到新的處理方法,但這顯然對將現有的 240 k 行代碼轉化到 six 作用不大。我們都有使用舊語法的壞習慣,這可以說是教學上的成功了,即使它對代碼行的計數沒有什么不同,它也被我們用于實驗分支:

實驗分支

我新建了一個名為“Python 3 ”的分支,并做了以下操作:

  • 在整個代碼庫上運行“python-modernize -n -w” 。它會在合適的地方修改代碼。我經常做完這步后沒有進行第一次提交就開始修復代碼。這個錯誤步驟總是讓我后悔,不止一次地迫使我重新開始做整件事情。即使這個階段出錯,最好還是先把它提交。因此將機器和人要做的事情分開顯得尤為重要。

  • 將所有用于函數體的依賴項導入到我們還沒有修復的 py3。

這里的想法是“run ahead”,即看看如果我們沒有使用過時的依賴項,我們會遇到什么問題。這個分支允許我在超級中斷狀態下可以非常快速地啟動應用程序,至少可以運行一些單元測試。 這個分支有很大的不同,但我還是找到了把它應用在適當場景的方法。我使用優秀的 GitUp 來拆分、組合和提交。當一個提交看起來不錯的時候,我會把它挑選到一個新的分支,然后發給代碼審查。

沒有人可以在這個分支上工作,因為它被不斷地 rebase ,強制推送,濫用,但是它確實讓項目向前推進了,而不用等待所有的依賴項被更新。我強烈推薦使用這種方法!

靜態分析

我們添加了預提交鉤子,所以如果您編輯了一個文件,就會收到建議將 Python 3 全部進行 modernize 更新的提示。

quote_plus 的手動靜態分析: 在處理 quote_plus 和 six 上有一些細微差別。最后,我們創建了自己的包裝器,默認代碼強制執行使用這個包裝器,而不是使用標準庫中的包裝器,也不使用 six 中包裝器。我們還靜態檢查了您從未給 quote_plus 發送過的字節。

我們修復了每個 diango 應用程序中所有的 python 3 問題,并在 CI 環境中使用一個白名單強制執行了這一點,所以您無法破壞一個曾經修復過的應用程序。

依賴

對于我們來說,解決依賴是最困難的部分。我們有很多依賴,所以花了很多時間,其中有兩個依賴關系比較棘手:

  • splunk-lib. 我們依賴于 splunk,但是直到今天,他們仍然忽略所有要求為客戶端增加 py3 兼容性的憤怒的客戶。我們團隊中的一個人 最后自己親自動手來解決這個問題。Splunk 處理得真的很糟糕,它甚至把這個評論區的這個問題鎖上了!這簡直讓人無法接受。

  • Cassandra. 我們的整個產品都在使用這個數據庫,但是我們使用了一個有以前 API 模塊的舊的驅動程序。對于我們來說,py3 的遷移過程中,這占據了很大的一部分,因此我們必須逐段重寫所有的這些代碼。

測試

我們的代碼測試覆蓋率大約有 65% 包括:單元、集成, 以及 UI 合并。 我們確實編寫了更多的測試,但總體數量并沒有發生太大的變化。考慮將覆蓋率從 65% 提高到 66% ,意味著編寫將近2000 行代碼的測試,這一點也不奇怪。

我們必須跳過需要 Cassandra 的測試,同時修復這個依賴項。 我發明了一個有趣的小 hack 來使它發揮作用, 并寫了這方面的文章.

代碼更改

關于代碼更改的說明,在如何將 py2 遷移到 six 的文檔中并未提及 (也許是我們錯過了):

StringIO

我們在代碼中大量使用 StringIO 。第一反應就是使用 six。但對于 StringIO 來說,這在幾乎所有情況下 (但不是全部!)都被證明是錯。基本上,我們必須非常仔細地考慮每一個我們使用 StringIO 的地方,并試圖弄清楚我們是否應該用 io.StringIO, io.BytesIO 或者 six.StringIO 來替代它。這里犯錯的表現通常為看起來像兼容 py3 的代碼準備好了,在 py2 中可以正常運行,卻實際上在 py3 中是失效的。

從 future 中導入unicode_literals

這是一件好壞參半的事情。您可以通過將它添加到許多文件中來發現 bug,但是有時會在 py2 中引入 bug。 當日志突然在奇怪的地方,比如在字符串前寫"u"時,它也會變得令人困擾。總的來說,這顯然不是我所期望的效果。

str/bytes/unicode

這在很大程度上是您所期望的。我感到驚訝的是,在 py2 和 py3 中需要 str 。如果將來您使用 unicode_literals 導入,那么一些字符串需要從 'foo' 修改為 str('foo')。

six.moves

six.moves 的實現是一個非常奇怪的***行為,因此它不像它假裝的普通 Python 模塊那樣運行。 我也不同意他們在 six.moves 中不包含 mock 的選擇。我們必須使用他們的 API 來自己添加它,但這讓我們很難開始工作,而且它要求我們將 from mock import patch 改為 from six.moves import mock 這也意味著 patch 現在變成了 mock.patch 。

CSV 的解析是不同的

如果你使用 csv 模塊,你需要了解 csv342。在我看來,這應該是 six 的一部分。否則就意味著你沒有意識到有問題。不過我們在許多地方都沒有使用 csv342,所以您這里要做的工作可能會有所不同。

發布順序

我們首先進行測試:

  • 在 CI 中進行單元測試

  • 在 CI 中進行集成和UI測試(不包括 Cassandra)

  • 在 CI 中進行 Cassandra 測試 (這要晚于之前的步驟!)

接下來就是產品本身了。我們建立一臺擁有能一次性切換到 py3 的能力的批處理機器,并且至關重要地是將其切換回來。當在 py3 上發生中斷時,這一點就顯得很重要了。這對我們來說是很好的,因為我們可以重新排隊那些中斷的任務,但是我們不能中斷太多或者任何實際上是很關鍵的任務。我們使用 Sentry 來收集奔潰日志,所以很容易查看遷移到 py3 時遇到的所有問題,而且當我們修復了所有的問題時,我們需要再次遷移到 py3,直到我們得到一些問題,如此反復。

我們有如下環境:

  • Devtest: 開發人員在內部使用,所以大多數情況下,這只是用來測試數據庫遷移。這個環境非常容易使用,所以這里不經常出問題。

  • IAT (內部驗收測試):用于驗證更改,并在我們將更改推送到生產之前執行回歸測試。

  • UAT (用戶接受度測試): 客戶可以訪問的測試環境。用于需要準備客戶系統的變更,或者讓客戶在上線前查看變更。這個環境在數據庫遷移前幾天才會遷移。

  • 生產環境

我們按照以下順序將 Python 3 發布到這些環境中:

  • Devtest 環境

  • 短期 IAT 環境

  • 長期 IAT 環境

  • 一臺短期的批處理生產機器

  • 在工作期間使用的一臺批處理生產機器

  • 生產 SFTP

  • 占一半生產的批處理機器

  • 生產批次

  • 生產 Web (在測試環境的長時間手動測試運行之后)

  • 生產負載機器。這是批處理的一個特殊子集。它完成了我們產品中 CUP 和內存最多的部分。

負載機器暴露了與 Python 3 不兼容的客戶數據配置,因此我們必須在 Python 2 中實現對這些情況的警告,并確保再次打開 Python 3 之前已經修復了它們。這花了幾天時間,因為我們每天都會收到客戶數據,所以每次都會有一個警告,這又讓我們不得不再等一天。

生產中的驚喜

  • '?'.upper() 在 py2 中是 '?' 但是在 py3 中是 'SS' 。當產品的最后一部分遷移到 py3 時,最終導致了產品的崩潰!

  • 在 py2 中對不同類型的對象進行比較和排序是有效的,但這隱藏了大量的 bug 。我們得到了一些令人討厭的驚喜,因為這種行為以一些不明顯的方式從堆棧中泄露出來,特別是在一些排序列表中存在 None 的時候。總的來說,這是一個勝利,因為我們發現了相當多的 bug 。 None 在 py2 的列表中排在第一位,這可能會讓人感到驚訝(您可能會期望它被排序到接近于零的地方!), 現在我們只需要來處理它們。

  • '{}'.format(b'asd') 在 Python 2 中是 'asd' , 但是在 Python 3 中是 "b'asd'" 。在 Python 3 中,這里幾乎任何其他行為都會更好: 輸出為十六進制 ( 結果明顯更不一樣 ) ,舊的行為 (之前的代碼運行),或者拋出異常 (最好的行為!)。

  • int('1_0') 在 py 3 中結果是 10 , 但是在 py2 中無效。這甚至在切換到 py3 之前就困擾了我們。因為這種錯配導致了另一個在我們之前使用 py3 的團隊給我們發送了我們認為無效而他們認為有效的有效值。我個人認為這個決定是錯誤的:非常嚴格的解析是更好的默認方式,我擔心這將在未來幾年會繼續以微妙的方式困擾我們。

結論

最后,我們覺得在這件事上我們真的別無選擇: Python 2 的維護將在某個時刻停止,我們的依賴項僅限于 py3,最明顯的就是 Django。但是,無論如何,我們還是想要進行這種轉換,因為我們經常會被 bytes/Unicode 問題困擾,并且Python 3 僅僅是修復了 Python 2 中的許多小麻煩。這次遷移過程,我們已經在生產過程中發現了一些實際的漏洞/錯誤配置。我們也期待在任何地方都可以使用 f-string 和有序字典。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

梓潼县| 遂平县| 金塔县| 陆良县| 汕头市| 大埔县| 平罗县| 桐乡市| 遂平县| 南京市| 车致| 石楼县| 平罗县| 新兴县| 白山市| 黔南| 万源市| 安仁县| 望都县| 远安县| 威远县| 唐山市| 渑池县| 韶关市| 大邑县| 裕民县| 乐亭县| 孝义市| 开鲁县| 尼勒克县| 宁强县| 巴马| 南川市| 绥宁县| 磐安县| 黔南| 峨眉山市| 江孜县| 东城区| 江安县| 修文县|