Python Web开发模板引擎优缺点总结


Posted in Python onMay 06, 2014

做 Web 开发少不了要与模板引擎打交道。我陆续也接触了 Python 的不少模板引擎,感觉可以总结一下了。

一、首先按照我的熟悉程度列一下:

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 算了,其他的要么不好用,要么学习成本比较高,而且多出来的功能感觉并不是非有不可的。

Python 相关文章推荐
Python正则表达式匹配HTML页面编码
Apr 08 Python
Python手机号码归属地查询代码
May 04 Python
windows上安装Anaconda和python的教程详解
Mar 28 Python
Ubuntu安装Jupyter Notebook教程
Oct 18 Python
Python3.6基于正则实现的计算器示例【无优化简单注释版】
Jun 14 Python
使用python 对验证码图片进行降噪处理
Dec 18 Python
python 统计文件中的字符串数目示例
Dec 24 Python
python实现录屏功能(亲测好用)
Mar 02 Python
keras打印loss对权重的导数方式
Jun 10 Python
详解Python中下划线的5种含义
Jul 15 Python
Python爬虫中urllib3与urllib的区别是什么
Jul 21 Python
python3 字符串str和bytes相互转换
Mar 23 Python
windows系统中python使用rar命令压缩多个文件夹示例
May 06 #Python
Python中使用动态变量名的方法
May 06 #Python
python完成FizzBuzzWhizz问题(拉勾网面试题)示例
May 05 #Python
使用python实现拉钩网上的FizzBuzzWhizz问题示例
May 05 #Python
python通过scapy获取局域网所有主机mac地址示例
May 04 #Python
python使用内存zipfile对象在内存中打包文件示例
Apr 30 #Python
python数据结构之二叉树的统计与转换实例
Apr 29 #Python
You might like
PHP生成图片验证码、点击切换实例
2014/06/25 PHP
CI框架文件上传类及图像处理类用法分析
2016/05/18 PHP
PHP基于curl后台远程登录正方教务系统的方法
2016/10/14 PHP
使用 laravel sms 构建短信验证码发送校验功能
2017/11/06 PHP
Laravel 5.4.36中session没有保存成功问题的解决
2018/02/19 PHP
javascript radio 联动效果
2009/03/04 Javascript
用Javascript实现锚点(Anchor)间平滑跳转
2009/09/08 Javascript
JS特权方法定义作用以及与公有方法的区别
2013/03/18 Javascript
js实现鼠标拖动图片并兼容IE/FF火狐/谷歌等主流浏览器
2013/06/06 Javascript
二叉树的非递归后序遍历算法实例详解
2014/02/07 Javascript
详解js中构造流程图的核心技术JsPlumb(2)
2015/12/08 Javascript
js面向对象的写法
2016/02/19 Javascript
js类式继承与原型式继承详解
2016/04/07 Javascript
JS回调函数简单用法示例
2017/02/09 Javascript
Vue.js自定义事件的表单输入组件方法
2018/03/08 Javascript
基于js实现复制内容到操作系统粘贴板过程解析
2019/10/11 Javascript
js实现移动端图片滑块验证功能
2020/09/29 Javascript
基于elementUI竖向表格、和并列的案例
2020/10/26 Javascript
[01:10]3.19DOTA2发布会 三代刀塔人第一代
2014/03/25 DOTA
[02:09]抵达西雅图!中国军团加油!
2014/07/07 DOTA
对Python 获取类的成员变量及临时变量的方法详解
2019/01/22 Python
python定位xpath 节点位置的方法
2019/08/27 Python
树莓派3 搭建 django 服务器的实例
2019/08/29 Python
Python hashlib模块的使用示例
2020/10/09 Python
Python批量获取并保存手机号归属地和运营商的示例
2020/10/09 Python
Lacoste(法国鳄鱼)加拿大官网:以标志性的POLO衫而闻名
2019/05/15 全球购物
《鱼游到了纸上》教学反思
2014/02/20 职场文书
市场调查策划方案
2014/06/10 职场文书
交通局领导班子群众路线教育实践活动对照检查材料思想汇报
2014/10/09 职场文书
刑事辩护词范文
2015/05/21 职场文书
2016高一新生军训心得体会
2016/01/11 职场文书
2016个人先进事迹材料范文
2016/03/01 职场文书
pytorch 如何使用batch训练lstm网络
2021/05/28 Python
基于Redis结合SpringBoot的秒杀案例详解
2021/10/05 Redis
Win11 引入 Windows 365 云操作系统,适应疫情期间混合办公模式:启动时直接登录、模
2022/04/06 数码科技
windows安装 redis 6.2.6最新步骤详解
2022/04/26 Redis