- pyTenjin:我在開發 Doodle 和 91 外教時使用。
- Tornado.template:我在開發知乎日報時使用。
- PyJade:我在開發知乎日報時接觸過。
- Mako:我只在一個早期就夭折了的小專案裡用過。
- Jinja2:我只拿它做過一些 demo。
其他就不提了,例如 Django 的模板,據說又慢又難用,我根本就沒接觸過。
再說效能吧。
很多測試就是弄個大迴圈什麼的,很沒技術含量。其實模板的渲染時間主要消耗在字串處理上,包括拼接、編碼、轉義等,而迴圈測的則是 Python runtime 的效能。
所以我還是用實際的例子來測試吧,最終選擇了 Doodle 的首頁。它有幾個子模板、幾個迴圈、幾個函式呼叫和很多個變數,具有一定代表性。考慮到 pyTenjin 以外的模板引擎不支援區域性快取,我就把用到快取的側邊欄去掉了,只渲染主體部分。
渲染 1000 次的結果為:pyTenjin 耗時 0.65 秒,取消預處理後耗時 0.9 秒;Tornado.template 耗時 1.0 秒;Jinja2 耗時 1.1 秒。
測試程式碼有幾百行,19 個檔案,我就懶得列出來了。其他模板引擎也懶得測了。
pyTenjin 的優勢很明顯,特別是它支援預處理。這個預處理的主要作用是把一些常量先編譯好,渲染時就不用再處理了(因為已經變成字串了);此外,有些功能可以靜態地決定是否開啟,而預處理可以把那些不需要的功能程式碼(主要是 if 分支)提前去掉。此外還能快取任意程式碼段的渲染結果,在一段時間內無需重新渲染。
Jinja2 比 Tornado.template 慢是我沒想到的,好像與很多測試不符。
Mako 預計和 Jinja2 差不多。它也能快取程式碼段的渲染結果。
PyJade 需要把 Jade 模板轉成其他模板,且無快取,預計會慢很多。
考慮到除 PyJade 外肯定不存在幾倍的效能差距,所以挑個好用的即可。
最後說易用性吧。
- pyTenjin 的優點是可以寫任意 Python 程式碼。
缺點是標記比較複雜和獨特,有 <?py … ?>、<?PY … ?>、#{…}、#{{…}}、{==…==}、{#==…==#}、${…}、${{…}}、{#=…=#} 和 {#==…==#} 這麼多種,不過看上去還挺萌的。
由於使用了 < 和 > 符號,在 HTML 標籤內部使用時,會阻礙編輯器進行語法解析。
另外,它的 tagattr() 方法在 expr 引數為 0 時當成了 True 來處理,需要改原始碼來修正,而它又沒有開源專案可以提交 pull request。
而且它只有一個開發者,已經有一年多沒更新了,活躍度明顯不夠。 - Tornado.template 的優點是與 Tornado 搭配還不錯(畢竟是自帶的),功能和效能都還行。
缺點是出錯時很難定位到是哪寫錯了,而且與其他模板引擎相比,功能確實少了點(不過我還沒遇到不夠用的情況)。
另外,{% raw … %} 寫起來好麻煩。None 在輸出時會顯示成 None,而不是空字串,導致寫起來很累。
它輸出的 HTML 程式碼是去掉頭尾空格的,不過單獨的 Python 程式碼行會顯示成空行,看上去比較怪。 - Jinja2 的優點是功能多,定義了很多輔助函式,有 filter,也有內聯的 if 表示式這種語法糖,寫起來比較舒服。此外,它能夠調整空白,這使得它輸出的 HTML 比較好看。
缺點是學習成本較高,語法也不是純 Python 了,甚至不能 import Python 模組和使用 [item for item in list if item] 這種列表解析表示式。
另一個嚴重的缺點是不能輸出非 ASCII 的字串, 遇到這種情況必須使用 unicode 型別,但要保證這點很麻煩。 - Mako 的優點是和 pyTenjin 一樣可以寫任意 Python 程式碼,又和 Jinja2 一樣支援 filter(其實習慣了函式呼叫的話)。
缺點也是學習成本較高,語法比較複雜,對 HTML 編輯器不友好。 - PyJade 的優點是寫起來最快(特別是對前端而言),沒什麼多餘的東西。
缺點和 Jinja2 一樣,更慘的是它幾乎沒有文件,而且最新的 release 版不可用,需要用開發版。
目前看來,我還是繼續用 pyTenjin 算了,其他的要麼不好用,要麼學習成本比較高,而且多出來的功能感覺並不是非有不可的。