2011年7月17日 星期日

在 Python 2.7 and 3.x 之間的 Deprecations

原文網址: Deprecations between Python 2.7 and 3.x

最近 在 python-dev 上面的討論 提到了關於目前開發者所遇到的從 Python 2.7 到 Python 3.x 時,Python 的 deprecation 政策問題。 由於考慮到 Python 使用者通常會直接從 Python 2.7 轉移到目前的最新 3.x 版,而不會關心舊版本,開發團隊對 deprecation 方針做了修改。

背景

Python 對於向下相容性有很強烈的承諾,除非可以符合相容性方針,否則不允許做出任何改變。 基本上來說也就是原本正確的程式不能在新版本的 Python 當中出錯。然而,這並不是永遠都能做到的, 舉例來說,當有某個 API 有很嚴重的問題並且需要被其他 API 替代的時候。在這種狀況之下, Python 依照 deprecation 方針:當某些特性要正式被移除的時候,會有一年的轉換期。 在這段期間,必須要有 deprecation 警告訊息來讓開發者有時間更新他們的程式碼。 關於 Python 的 deprecation 方針的細節在 PEP 5 有詳細的說明。由於只有在新的 Python 發行版本會有改變, 而且在發行版本之間通常都間隔了 18 個月,因此一次發行的 deprecation 周期剛好符合標準。

對於這個方針的有個例外是 Python 3。從 Python 2 到 Python 3 之間的主要版號變更就是特別為了允許破壞向下相容性的變更, 讓開發者有機會可以修正在目前方針之下無法修正的問題。舉例來說,讓字串預設為 Unicode,還有回傳 iterators 而不是 lists。

平行開發

轉移到 Python 3 會花上些時間,很多人估計大概是 5 年左右,所以 Python 2 和 Python 3 會平行開發一段時間。

由於 Python 2.7 會是 Python 2 的最終發行版本,大家都同意它的維護其將會被延長一大段時間。最後, 想要移到更新版本的開發者會需要跳到 Python 3。

以下是其中一個問題...

令人驚訝的 deprecation

一個 python-dev 的討論串 當中, 有個人指出了在 C API 當中的某個特定函式 PyCObject_AsVoidPtr 被移除了而沒有出現足夠的警告訊息。 然而這跟 deprecation 方針是相違背的!發生了什麼事情?

這個變更是從舊的 API (PyCObject) 轉移到更新、更好的 API (PyCapsule) 的一部份。 問題在於 PyCObject 在 Python 2.6 當中是預設而且唯一可用的 API。它在 Python 2.7 當中已經被標為 deprecated 了。 在 Python 3.2 這個 API 並不存在並且應該使用新的 PyCapsule 。這造成了一段大約七個月的 deprecation 周期 - 從 Python 2.7 的發行 (2010 年 7 月) 到 Python 3.2 的發行 (2011 年 2 月)。這比十二個月的最短周期還短的多, 並讓開發者很難對 Python 的發行版本做支援。

對於從 3.0 升級到 3.1 接著升到 3.2 的人來說,這個 deprecation 過程沒啥問題。 Python 3.1 在 2010 年 3 月發行時有這個 deprecation,並且在 3.x 的發行系列也都有, 因此有著將近 12 個月的的 deprecation 周期。但是這並不是人們通常的作法: 他們直接從 2.7 升級到最新的 3.x 版 (在這個案例是 3.2) 而造成了這個問題。 這從來不是 python-dev 的用意,但是 PEP5 提出的時候並沒有考慮到 Python 會同時有正在積極開發的並行版本。

所以我們該怎麼辦?

儘管 PyCObject/PyCapsule API 是個明顯的問題,這並不是不可能被處理的。 但是在 python-dev 上面至少有一個人為了處理這個問題遇到了一些困難。總而言之,這一切都不應該發生。

對於``PyCObject``/PyCapsule 的特例來說,這個問題已經存在而且我們也不能做些什麼。 重新恢復 PyCObject` 並不是一個選項,這將會增加更多的不相容性。然而,儘管會很繁瑣, 一般來說是可以寫出適合當前有提供的 API 的程式碼。事實上,在 Python 3.1 中, PyCObject API 是寫成 PyCapsule 的 wrapper。有人建議說如果有任何人需要, 在 Python 3.1 中的實作可以抽出來讓第三方程式碼使用。另外,大家也同意對於這變更要寫一份「有追溯力」的 PEP, 以便敘述在這變更之後的原因,並且說明可以幫助開發者轉移的資源。

簡單來說,Python 開發團隊現在已經認知到有這個問題並且會避免它再度發生。Guido 對這個狀況 發表了評論 並且建議目前 Python 3 對於 deprecations 的使用必須要保守一點。至少 deprecated API 在被移除之前必須要存在足夠久的時間, 給予從 2.7 轉移的開發者一條路走。

間接來說,這個討論串提出了要如何在短時間內有效率的讓 Python 的變更可以跟更多的人做交流, 這也是建立這個部落格想要解決的問題。

這些代表了什麼?

首先,這代表了 Python 開發者並不一定總是對的。沒人會想要讓開發者日子過得更苦,只是沒有及時發現這個問題。

再來,解決這個問題可能會帶來更多的麻煩,所以 PyCObject API 沒有重新被啟用。 儘管重新恢復 API 可能會幫助那些被這個變更傷害到的開發者,總體來說這會讓相容性問題更加的複雜。 同時,我們必須容忍這問題並且繼續往前邁進。我們已經學到了教訓,下次不會再犯下相同的錯誤。

這件事情也表現出 Python 開發團隊希望聽取使用者的意見。相容性是相當重要的, 大家也為了可以無痛轉移到新版本盡了每一份心力。尤其是函式庫的開發者會在合理的努力下希望能夠支援多個 Python 版本。

最後,開發者並沒有拋棄 Python 2.7,儘管在 2.7 並不會有新的特性,未來也不會有 Python 2.8 ,2.7 版使用者的看法還是很有影響力的。 讓使用者可以順利轉移到 3.x 版對整個 Python 社群來說是很重要的。

2 則留言:

kynix 提到...

感謝各位辛苦翻譯! 品質真的很好! 小弟在這邊向大家加油!

TIM's Thought 提到...

謝謝鼓勵 :) 希望這些文章可以幫助大家用更少的功來一起深入Python.

張貼留言