Python模板引擎Jinja2使⽤简介
背景
最近在项⽬开发中,需要针对 Jenkins 项⽬进⾏配置,Jenkins 的 job 配置采⽤的是 xml,在维护配置模板的过程中就遇到了问题,因为逐步发现配置灵活性超出了字符串的范畴,本⽂旨在简单介绍 Python 下模板引擎模块 Jinja2 的使⽤。
什么是 Jinja2?
Jinja2 是⼀个 Python 的功能齐全的模板引擎。它有完整的 unicode ⽀持,⼀个可选的集成沙箱执⾏环境,被⼴泛使⽤,以 BSD 许可证授权。
以上是官⽅说明,简单来说,它提供了替换功能(变量替换)和⼀些强⼤的特性(控制流、继承等),可以快速⽣成数据⽂件,使得业务与数据分离开来,满⾜⼀些灵活多变的配置需求。
为什么要使⽤ Jinja2?
拿 Jenkins 配置来说,如果要实现不同平台、不同项⽬的配置,有以下⼏种⽅案:
1. 直接进⾏字符串替换,使⽤ Python 字符串语法即可
2. 使⽤ XML 解析和⽣成模块,⽐较简便的是 ElementTree
3. 使⽤模板引擎,例如 Jinja2
起初,我选⽤的是⽅案⼀,特点是简单粗暴,不需要额外的配置,例如,两个项⽬的 git 仓库配置可以采⽤如下代码实现:
# 略去不相关代码
template = b"""<configVersion>2</configVersion>
<userRemoteConfigs>
<hudson.plugins.git.UserRemoteConfig>
<url>%(git_url)s</url>
</hudson.plugins.git.UserRemoteConfig>
</userRemoteConfigs>
<branches>
<hudson.plugins.git.BranchSpec>
<name>%(git_branch)s</name>
</hudson.plugins.git.BranchSpec>
</branches>"""
xml = template % {'git_url':self.__git_url, 'git_branch':self.__git_branch}
这样,只需要外部传⼊地址及分⽀,即可获得不同的项⽬配置 xml,但缺点也很明显如果两个配置节点数⽬不相同或者⾥⾯的字段差别很⼤,那么就需要使⽤template2、template3、template4等等,因此此⽅案仅适合配置需求较为简单,字段不是很复杂的场景。
紧接着,开始调研快速⽣成不同 xml 数据的⽅案,到了这⾥提到了两种⽅案,也就是上述的2、3。
⽅案2的特点也很明显,可以完整控制 xml 中每个字段和属性,灵活性确实够了,能够满⾜我们的需求,但是有点⼤炮打蚊⼦的感觉,⽽且频繁的读写 xml 也⽐较消耗性能,业务逻辑也会随着配置的灵活性和多样性急遽膨胀,⽐如 Jenkins 项⽬配置,仓库地址、分⽀信息、ssh 信息、tag 字段、打包脚本等等,如果使⽤ xml 解析的话,针对这些节点都必须创建对应的业务逻辑,不是很推荐。
那么我们的选择也⽐较简单了,Jinja 可以快速的替换⽣成我们业务需要的各种各样的数据,⽽且接⼊成本低,业务逻辑不会变化太⼤,下⾯简单介绍下本次项⽬中的使⽤。
Jinja2的简单使⽤教程
安装
这个⽐较简单,看下⽂档即可,执⾏命令
pip install jinja2
python处理xml文件基本概念
Jinja2中有⼀个名为Environment的对象,⽤于存储配置、全局变量,并且⽤于从⽂件系统中加载模板。即使你通过Template⽤字符串创建⼀个模板,Jinja2 也会⾃动为你创建⼀个环境。推荐使⽤这种⽅式进⾏模板配置⽽不是使⽤字符串,⼤多数程序使⽤⼀个环境即可。
⽤法
1. 创建⼀个环境:
from jinja2 import Environment, PackageLoader, select_autoescape
# 初始化 jinja 环境
self.__env = Environment(
loader=PackageLoader('模块名称', '模板⽂件夹'),
autoescape=select_autoescape(['html', 'xml'])
)
1. 加载⼀个模板:
self.__job_template = self.___template('l')
2. 接下来就是传递⼀些业务参数了,
self.__config = self.__der(
git_url=self.__git_remote_url,
git_branch=self.__git_branch,
git_tag=self.__git_tag
)
以上都还是⽐较简单的 API 调⽤,核⼼使⽤部分在与如何在模板中通过 Jinja ⽀持的语法灵活的进⾏数据配置。
基本变量替换
最基础的功能就是进⾏变量替换了,语法为{{变量名}},例如将 url 传递到 xml 中,模板中写法为(省略了不相关内容):
<userRemoteConfigs>
<hudson.plugins.git.UserRemoteConfig>
<url>{{git_url}}</url>
</hudson.plugins.git.UserRemoteConfig>
</userRemoteConfigs>
然后在代码中向上⾯⼀样调⽤der(git_url='xxx')即可
控制流
Jinja ⽀持基本的if、for、宏等语法,这也是它最强⼤的地⽅,⽬前项⽬中我只⽤到了判断就够了。⽤法如下:
{% if push_tag %}
<tagsToPush>
<hudson.plugins.git.GitPublisher_-TagToPush>
<targetRepoName>origin</targetRepoName>
<tagName>{{git_tag}}</tagName>
<tagMessage></tagMessage>
<createTag>true</createTag>
<updateTag>true</updateTag>
</hudson.plugins.git.GitPublisher_-TagToPush>
</tagsToPush>
{% endif %}
上⾯这段 xml 的逻辑就是如果传⼊了push_tag变量且为True则在 Jenkins 配置中增加推送 git tag 节点,否则不做任何处理。
除此之外,Jinja2 还⽀持循环,
<dl>
{% for key, value in my_dict.iteritems() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
详细说明可以参考
继承
这部分由于⽬前项⽬配置还⽐较简单,暂时没⽤到,可以参考
结语
对于简单的项⽬来说,上⾯提到的⼀些基本替换加控制流基本都能满⾜使⽤了,稍微复杂⼀点的程序可以考虑使⽤继承和扩展。
总的来说,Jinja2 既强⼤⼜简便,完美符合项⽬中⼀些HTML、XML 的业务配置需求,⽬前项⽬中本⾝有的三四个 xml ⽂件⽤了 Jinja2 之后缩减成⼀个,同时改动⼯作量⼤约只花了⼏个⼩时,真的很⽅便。
参考资料:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。