2011年8月24日 星期三

認識核心團隊:Benjamin Peterson

原文網址 Meet the Team: Benjamin Peterson

這篇文章是「認識核心團隊」系列文章的一部分,目的是對 Python 核心開發團隊的成員來個簡短的介紹

姓名:Bejamin Peterson
位置:美國明尼蘇達州 (Minnesota, USA)
首頁:http://benjamin-peterson.org
部落格:http://pybites.blogspot.com

你使用 Python 有多長時間了?

三年半

你成為核心開發者有多久了?

到今年三月二十五號剛好滿三年

你是如何開始成為核心開發者的?你記得你第一次的提交嗎?

我第一次提案被 Guido 本人否決了 。幸運的是,我繼續堅持了下去並且也有些 patch 被接受了。我想我第一份提交是調整 Misc/ACKS 檔案的順序。

你現在負責 Python 的哪些部分

我喜歡語法分析器、編譯器以及直譯器的核心部分,不過大家都知道除了Windows 相關之外,我涉足於幾乎每一個 Python 的核心開發部分。

當你沒有在處理 Python 核心開發相關工作的時候,你都用 Python 來做些什麼?

我用它來實作 Python 直譯器 (http://pypy.org)!說真的,我打從心裡就是一個 Python 的實作者。 我是 six (http://pypi.python.org/pypi/six) 的創造者,six 是一個處理 Python 2 和 Python 3 之間相容性的程式庫。

當你沒在寫程式的時候你都在做些啥?

做音樂,吹豎笛還有讀些數學書,另外有時也會跑去爬山。

Python 核心開發輔導計畫

原文網址 The Python Core Mentorship Program .

Jesse Noller 在最近公告了 Python核心輔導 計畫 ( the Python Core Mentorship Program ), 這個計畫要讓學生,以及其他的專案的開發者可以得到導師的指導來降低進入 Python 核心開發的門檻。 而導師將會由有貢獻過 Python 核心程式碼經驗的程式設計師來擔任。

需要你的貢獻

不論你的經驗是多是少,導師們都會盡快回答問題,以親切的態度來給予回應。 想要貢獻程式碼的人會在整個開發流程中全程得到指導。像是如何在 mailing list 中討論問題,使用 bug tracker, Mercurial, code review,以及其他各種幫助。

Early Success

這個計畫目前已經在成功運作之中,參加者已經活躍地提交了許多patch。 在 mailing list 中也有相當多有建設性的討論,帶領人們在各個議題之中往正確方向前進。

準則

當想要貢獻程式碼時,新手可能不知道該如何拿捏與導師互動的分寸,也不知道如何善用mailing list。 因此、我們在這個 website 擬定了一份準則來舒緩疑慮。 長遠來看,這不只是對 Python 核心開發有所幫助, Jesse 以及其他的導師更希望這個計畫可以成為其他專案的典範,也期待可以增加 Python 核心開發者的多樣性。

報名吧

整個計畫是運作在 mailing list 上,也有一個清楚又明確的 website 。 你可能是個正要加入社群開始貢獻程式碼的菜鳥,也可能是個老手但依然對各方面充滿疑問。 這是一個絕佳的好機會來深入Python核心。加入我們,開始問問題吧,你將會在實作中得到寶貴的經驗。

2011年8月8日 星期一

Windows 的 Python 啟動器 ( Launcher )

原文網址: A Python Launcher For Windows

Mark Hammond ( pywin32 的作者及 Windows 上的 Python 長期支持者 ) 寫了 PEP 397 ,描述了 Windows 下新的 Python 啟動器。Vinay Sanjip ( 標準程式庫 logging 模組的作者 ) 最近實做了這個啟動器,下載地址是 https://bitbucket.org/vinay.sajip/pylauncher/downloads

啟動器允許 windows 上的 Python 腳本 ( .py and .pyw 檔案 ) 選擇要使用的 Python 版本,並可同時運行 Python 2 與 Python 3。

Windows 使用者可考慮下載並測試啟動器,幫助 Python 開發人員解決剩下的問題。該啟動器是獨立打包的應用程式,將支援目前可用的 Python 版本。我們的目標是當完成了一個啟動器,就將其加入 Python 3.3 中 ( 當然我們將會提供獨立下載包給之前版本的使用者 )

這個啟動器有兩個可用的版本 - launcher.msi 會安裝到 Program Files 目錄,而``launchsys.msi`` 會安裝到 Windows 的 System32 目錄底下。 ( 我們也提供 64位元 windowsws 的安裝版 )

啟動器的一些細節

完整的 PEP 397 啟動器行為規範,概括如下:

  • 該起動器提供兩個可執行檔 - py.exe ( 命令視窗版 ) 和 ``pyw.exe`` ( GUI 版 )。
  • 啟動器註冊了 .py ( CLI ) 和 .pyw ( GUI ) 檔案的副檔名 ( file extension ) 。
  • 當執行腳本時,啟動器會從腳本中找出 Unix 風格的 Shebang 識別 #!``。他會識別出可執行的 ``python ( 系統默認的 Python 版 ), python2 ( 預設的 Python 2 發行版 ) 和 python3 ( 預設的 Python 3 發行版 ) 這幾個字樣。各使用者或各臺機器可輕鬆地客製化設定確切的細節。
  • 單獨執行 py.exe 命令,會啟動 Python 交互解譯器。可由命令列參數設定欲使用的 Python 版本, py -2 啟動 Python 2 , py -3 啟動 Python 3,和 py 啟動預設的 Python 版本。

簡單的使用說明

安裝完成後,啟動器會自動關聯 .py and .pyw 檔案。 除非你有更改,腳本會使用機器預設的 Python 執行。有一樣設定你可能會喜歡,如果你經常使用命令視窗的話,增加 .py 到環境變數 PATHEXT 中,腳本就不用再額外開啟命令視窗執行了。

指定腳本使用 Python 2,只要簡單的將下面格式寫在第一行即可:

#!/usr/bin/env python2

( 上為相容於 Unix 的格式,如果你不需要與 Unix 相容,可用 #!python2 代替 )

另外,如果你想要指定腳本使用 Python 3,需在第一行增加:

#!/usr/bin/env python3

你也可以使用下列指令來啟動 Python 解譯器:

# Default version of Python py # Python 2 py -2 # Python 3 py -3

上述設定要能執行,必須先將 py.exe 加入環境變數。 launchsys 版的啟動器安裝程式會自動幫你做這個設定,但是需要你手動將 launcher.msi 的安裝目錄 ( C:\Program Files\Python Launcher ) 加入至環境變數 PATH 中。

延伸閱讀

下面幾個 python-dev 郵件組涵蓋了一些關鍵內容:

2011年8月7日 星期日

CPython 3.2.1 釋出

原文網址: CPython 3.2.1 Released

Python 的核心開發者、發佈經理(Release Manager) Georg Brandl 代表 Python-dev 團隊宣布 CPython 3.2.1 正式釋出。Windows 的安裝套件與 tarball 包已經在 7 月 10 日釋出。各位可以考慮升級到這個版本囉!

What's New 文件詳細列出 3.2 版的新特性,原始碼裡的 Misc/NEWS 檔案則列出所修正的 bug。

如果你在該釋出版或其他版本有發現任何問題的話,歡迎回報至 http://bugs.python.org/ 給開發者們。

2011年7月24日 星期日

輪詢對 future 模組及平行處理的影響

原文網址: Of polling, futures and parallel execution

現今的電腦運算最引人關注的問題之一就是如何省電。可攜式裝置對電力的使用更是錙銖必較。 當CPU閒置時,CPU可以進入各種低耗能的狀態。閒置的狀態持續得久,就會進入更深層的低耗能狀態, 也就會更加省電。因此充一次電,你的電池就可以撐得更久。

低耗能狀態有一個致命的大敵: 輪巡( polling ),若有一個工作(task) 定時地讓CPU離開閒置狀況, 不管所做的工作有多麼的簡單(好比只是檢查記憶上的一個數值),都會讓CPU 離開低耗能狀態, 把CPU內部所有組件都喚醒,卻在工作完成很久以後才會再進入低耗能閒置狀態。 這大大地減低了電池的壽命, 而 Intel 也關注這個 問題

Python 3.2 標準程式庫加入了一個新的模組 concurrent.futures module 來平行啟動工作並且會等待工作結束。當我在看這個模組的程式碼時, 我注意到它在部份的Worker thread 及 Worker procees 之中使用了輪詢。 我說部份是因為是因為 ThreadPoolExecutor 以及 ProcessPoolExecutor. 之間的實作是不一樣的。前者每一個worker thread 都輪詢, 而後者只會在負責溝通各個 worker process 的 management thread 輪詢。

輪詢這在裡只有一個作用: 偵測該何時啟動關閉程序。 其他的工作像是把 Callable 物件放進 queue 或是把運算的結果從 queue 裡面拿出來,是使用同步的 queue。 這些 queue 物件是由 threading 或是 multiprocessing 模組所提供的, 依照不同executor 實作而會使用不同的queue。

所以,我想到了一個簡單的 解法 : 我把輪詢換成了一個 sentinel, 就是內建的 None。 當queue 收到了 None, 一個在等待的 worker, 會自然地被喚醒然後去檢查是否該被關閉。 在 ProcessPoolExecutor 的實作裡, 情況會變得比較複雜, 因為我們不只是要喚醒一個 queue management thread, 更要額外喚醒多個 worker process。

在我一開始的patch 裡面,我還是會將論詢的timeout 設定為一個非常大的區間 (10分鐘), 因此 workers 將可以在某個時間點被喚醒。 會存在這麼大的timeout, 是為了避免有 bug 的程式碼讓程式沒有辨法經由前面說到的 sentinel 來執行關閉的程序。 出於好奇心,我觀察了一下 multiprocessing 的程式碼而且發現到了另一個有趣的問題。 在windows 平台上,當 multiprocessing.Queue.get() 在設定一個非零,非無限大的timeout的時候,windows 會使用...輪詢 ( 對此,我開啟了 issue 11668 )。 這個實作方式會使用迴圈加上高頻率的輪詢, 而每一次的輪詢會增加千分之一秒的 timeout。

不用說,這種時常喚醒系統的方式讓我的 patch 在 windows 上失去了我想達到的效果。 所以,我就把那個 10 分鐘的 timeout 移除了。 因為把這個timeout 設定移除了,那不管在那一個平台, 都不會再有系統被定期喚醒的問題了。

在 Python 3.2 以前,threading 模組及使用了 worker thread 的 multiprocessing 模組中的 timeout 機制都使用了輪詢,這將會在 issue 7316 中被修正。

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 社群來說是很重要的。

2011年7月3日 星期日

2011-04-06-正規化AST的異動控管策略

原文網址: Formalizing the AST Change Control Policy

Python 在 AST 模組中公開了抽象語法樹(abstract syntax tree [1], AST)用來呈現Python原始碼編譯過的形式。 AST 模組容許使用者的程式碼在原始碼分析與編譯過的bytecode之間對AST 表達式(representation) 進行檢視與操作。

雖然Python 原始碼的語義已經在 language reference 中被定義了,AST 模組只是CPython的實作細節,在其它的Python實作版本中沒有必要去實作它。

AST模組相容性

某些 工作 中需要在AST上對CPython 中的區域程式碼優化器(peephole optimizer [2] )進行全面改寫(而不是在bytecode 這層,就這個case 而言),為此 Eugene Toder 需要對AST的結構進行修改。AST 作為一個CPython實作上的細節,沒辦法立即明瞭它是否也採用向後相容策略。 為此, Eugene向python-dev 問了這個問題 。 在修改AST時是否需要確保它的向後相容性?

一般來說社群裡一致同意 沒必要 去考量向後相容。AST 模組對外公開了一個常數 ast.__version__ , 讓使用者的程式碼得以依照AST的版本資訊對於它的程式行為自行調整。對於一個與實作版本相關的模組而言,這 樣子已經提供了足夠的相容性了。

其它 Python 的實作版本

事實上,Jython 和 IronPython 的維護者們指出他們各自的實作版本要嘛擁有一個相容的AST模組或是 傾向提供一個。即便如此,他們並不認為這代表 AST 模組應該被凍結發展並且樂見隨著 ast.__version__ 常數的更動,能在不用考慮相容性下修改AST模組。

有一個被提出的觀點指出在 test_ast.py 中的完整 test suite 可以幫助其它的實作 版本確保它們的 AST 表達式與 CPython 相容。 增加 test_ast.py 的涵蓋對於想要參與 Python 內部運作的的人們是一個好的 Project。

之後會發生什麼?

開啟這個討論串的 patch截至目前為止尚未 被整進 CPython中。 有可能,什麼事都不會發生。無論如何,如果它真的被commit了,AST 將會 以不向後相容的形式存在。 ast.__version__ 這個常數將會隨之更動來對應, 這樣子使用者們的程式碼才會知道可是程式也要隨之改動。概括來說,這將是未來AST更動 後要處理的方式。

Python 的開發者們對於這個策略被採用後,對已使用 AST的程式影響有多廣多深很有興趣。 如果有讀者們的程式會因為AST變更而受到影響,鼓勵大家去參與 在python-dev上的討論


[1]譯註: 關於 AST 可參閱 Wiki上的解釋
[2]譯註: 它的基本概念是為瞭解決statement by statement translation 可能會產生冗餘code的問題, 所以它在最佳化的時候是一次看一小段程式碼進行優化的動作,可以參閱 薛智文老師的投影片Wiki上的解釋