mako模版库实践

介绍

这几天在编写一个数据驱动测试框架,其中一个核心模块是根据数据输入,自动转换为测试用例代码。测试数据格式固定,对应的用例代码结构也相对稳定。基于此场景,联想到web页面根据数据从template渲染页面,决定使用类似的方式,采用模版库动态生成测试用例代码。
Python库有两个常用的模版库:Jinja2和Mako。两个库功能都很齐全强大,Jinja2广泛用于各种语言环境如Java/Go,Mako主要用于Python语言环境。
Mako模板从一个包含各种类型的内容的文本流解析得到,包括XML、HTML、email文本等。模板还可以包含Mako指令,用来表示变量和表达式替换、控制结构、服务器端注释、整块Python代码,还有用来提供额外功能的各种标签。所有这些结构都被编译为实际的Python代码。
Mako能直接嵌套Python代码,更贴近python代码风格,项目使用的也是python语言环境,使用起来更加方便,网上也有说mako库解析速度更快,我们最终选择了mako库。

使用方式

下面总结一下mako使用方式。
使用Template
通过from mako.template import Template引入mako模板。
1)基本用法

from mako.template import Template
t = Template("Hello,${name}")
print(t.render(name = 'world'))

输出:

Hello,world

2)导入模版文件
Template函数还有一些常用的参数:

  • filename:指定从文件中加载模板。最好用相对路径,否则缓存文件会包含在很长的路径下
  • module_directory:缓存目录。从文件中加载模板,可以指定module_directory生成.py文件缓存,提高加载速度。

例如:
新建一个模版文件demo.tmpl,保存以下内容:

Hello,${
   name}

使用模版代码:

from mako.template import Template
t = Template(filename="demo.tmpl", module_directory="./")
print(t.render(name='world'))

代码执行以后,当前目录下会生成一个以模版文件名,再加上后缀“.py”的缓存文件。
在这里插入图片描述
rend()方法会创建一个Context对象,该对象会存储所有render()方法传递给模版的变量,并且会保存为buffer用于捕获output输出。
我们也可以自定义Context对象,然后用 render_context()方法渲染。

from mako.template import Template
from mako.runtime import Context
from io import StringIO

mytemplate = Template("hello, ${name}")
buf = StringIO()
ctx = Context(buf, name="python")
mytemplate.render_context(ctx)
print(buf.getvalue())

使用TemplateLookup
实际项目中,通常会有多个模版文件,组合渲染一个页面。这种情况下,我们可以使用TemplateLookup,直接从指定的目录导入多个模版文件。

from mako.lookup import TemplateLookup

lookup = TemplateLookup(directories=['./templates'], module_directory='./', collection_size=500, filesystem_checks=True)
"""
# 使用templateLookup,可以方便的设置模板目录,当模板中include别的模板时可以只写模板名
# collection_size设置加载到内存中的模板上限
# filesystem_checks为True会在每次加载模板缓存判断模板文件是否有改动,会重新编译。
"""
def serve_template(templatename, **kwargs):
    mytemplate = lookup.get_template(templatename) #get_template()方法根据文件名,获取指定的template
    print(mytemplate.render(**kwargs))

serve_template("index.html", name="python")

异常处理
异常主要出现在查找并解析模版文件,以及渲染模版两个场合。渲染阶段的异常主要是python自带的异常。mako封装了异常类处理模版解析过程中的异常堆栈,将堆栈数据格式输出化为text或者html格式。
text_error_template() 输出text格式异常堆栈;html_error_template() 输出html格式异常堆栈。这两个方法本质上都是调用sys.exc_info()获取程序最近抛出的异常。

  • text模版异常
from mako import exceptions
try:
    template = lookup.get_template(uri)
    print(template.render())
except:
    print(exceptions.text_error_template().render())
  • html格式模版异常
from mako import exceptions

try:
    template = lookup.get_template(uri)
    print(template.render())
except:
    print(exceptions.html_error_template().render())
  • 自定义异常:
    exceptions类底层使用的RichTraceback对象。该对象也可以用来自定义异常。
from mako.exceptions import RichTraceback

try:
    template = lookup.get_template(uri)
    print(template.render())
except:
    traceback = RichTraceback()
    for (filename, lineno, function, line) in traceback.traceback:
        print("File %s, line %s, in %s" % (filename, lineno, function))
        print(line, "\n")
    print("%s: %s" % (str(traceback.error.__class__.__name__), traceback.error

语法

表达式替换

  • 最简单的表达式是变量替换。语法为 ${var}
    Hello, this is my name: ${var}
    上面的例子会把 var 的字符串表示输出到模板的输出流。 var通常来自于传递给模板渲染函数的 Context 。如果没有传入x 给模板,并且也没有本地赋值,那么就等于一个特殊的值 UNDEFINED 。
    例如,模版文件demo.tmpl包含以下内容:
Hello, this is my name: ${
   name}
print(${
   version})

但是render()方法没有传递version参数时,会抛出异常“NameError: Undefined”

from mako.template import Template
t = Template(filename="./templates/demo.tmpl", module_directory="./")
print(t.render(name='world'))

运行结果:

Traceback (most recent call last):
  File "/Users/bruce.xu/mako/basic_usage.py", line 19, in <module>
    print(t.render(name='world'))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mako/template.py", line 476, in render
    return runtime._render(self, self.callable_, args, data)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mako/runtime.py", line 883, in _render
    **_kwargs_for_callable(callable_, data)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mako/runtime.py", line 920, in _render_context
    _exec_template(inherit
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值