Python -- jinja2模块学习与应用
为什么用jinja2
- 遇到的问题:工作中遇到需要从一个文件(xlsx之类)传入相关参数,根据某个模板生成一个代码文件。此时想到了python jinja2。
- 模板概念:模板简单来说就是一个其中包涵占位变量表示动态的部分的文件,模板文件在经过动态赋值后,返回给用户(该过程:可以理解为渲染)
python中自带一个简单的模板,就是string提供的。
>>> import string
>>> a = string.Template('$who is $role')
>>> a.substitute(who='daxin',role='Linux')
'daxin is Linux'
>>> a.substitute(who='daxin',role='cat')
'daxin is cat'
Python自带的模板功能极其有限,如果我们想要在模板中使用控制语句,和表达式,以及继承等功能的话,就无法实现了。目前主流的模板系统,最常用的就是jinja2和mako
一个简单的例子
## 一个简单的模板应用
from jinja2 import Template
template = Template('Address is {{ addr }} ')
template.render(addr = '0x0')
>>'Address is 0x0 '
模板的导入:
-
方法1:PackageLoader包加载器
- PackageLoader()的两个参数为:python包的名称,以及模板目录名称(个人是在当前路径下建立一个mypackage.py的文件,PackageLoader根据包文件所在的目录下查找templates文件夹)。
- get_template():获取模板目录下的某个具体文件。
from jinja2 import PackageLoader, Environment, FileSystemLoader
## PackageLoader 方法
## --(个人是在当前路径下建立一个mypackage.py的文件,PackageLoader根据包文件所在的目录下查找templates文件夹)
env = Environment(loader=PackageLoader('mypackage', 'templates'))
temp = env.get_template('temp_0.txt') ## 选择模板
-
方法2:FileSystemLoader文件系统加载器
from jinja2 import PackageLoader,Environment, FileSystemLoader
## FileSystemLoader 用法
path_dir = r'D:\Python\INNO_DDR\jinja2\templates' ## 设置templates所在的路径
loader = FileSystemLoader(path_dir)
env = Environment(loader=loader) ## 加载env类对象
temp = env.get_template('temp_0.txt') ## 选择模板
jinja2模板怎么写
-
在jinja2中,存在三种语法:
-
- 控制结构 {% %}
- 变量取值 {{ }}
- 注释 {# #}
-
jinja2的控制结构
jinja2中的if语句类似与Python的if语句,它也具有单分支,多分支等多种结构,不同的是,条件语句不需要使用冒号结尾,而结束控制语句,需要使用endif关键字。
1
2
3
4
5
6
7
|
{% if daxin.safe %} daxin is safe. {% elif daxin.dead %} daxin is dead {% else %} daxin is okay {% endif %} |
-
jinja2的for循环
jinja2中的for循环用于迭代Python的数据类型,包括列表,元组和字典。在jinja2中不存在while循环。
迭代列表
1
2
3
4
5
|
<ul> {% for user in users %} <li>{{ user.username|title }}</li> {% endfor %} </ul> |
迭代字典
1
2
3
4
5
6
|
<dl> {% for key, value in my_dict.iteritems() %} <dt>{{ key }}</dt> <dd>{{ value}}</dd> {% endfor %} </dl> |
当然也可以加入else语句,在循环正确执行完毕后,执行
- 一个简单的模板实例(temp_0.txt):
//-- Date: {{ time }}
//-- 以下以{{ module_name }} 为例:
{% for (i, j, k) in addr_list %}
addr = {{ i }}, mask = {{ j }}, default = {{ k }}
{% endfor %}
模板参数怎么传入
- 向模板中传入变量值,有两种方法,一种是像关键字参数一样传参,另一种是传入字典
- 实例:从一个xlsx文件传入,用DataFrame处理
input_file = r'D:\Python\test.xlsx'
input_dir = os.path.dirname(input_file)
df = pd.read_excel(input_file, sheet_name='Sheet1', skiprows=0)
## DdataFrame 传入多个参数
addr_list = zip(df['Addr'], df['Mask'], df['Default'])
## 定义特定字典参数
context = {
'time': ctime(),
'module_name': 'CTL_REG'
}
......
## 渲染并导出
temp.stream(context, addr_list=addr_list).dump('addr_list_v-1.h')
渲染并导出文件
-
render([context]) 向模板中传入变量值,有两种方法,一种是像关键字参数一样传参,另一种是传入字典
-
generate([ context] ) 对于非常大的模板,不能一次性渲染,而要采用分段渲染时,采用此函数
-
stream([ context] ) 和generate一样,但返回一个TemplateStream对象
## render 方法
s1 = temp.render(context, addr_list=addr_list) ## render渲染方法, 生成字符串, 不能使用dump方法
print(type(s1))
## 保存基于模板生成的文件
with open(os.path.join(path_dir,'..','ddr_addr.h'), 'w') as o_file:
o_file.write(s-1)
## stream 方法, 生成TemplateStream, 可使用dump方法将整个流写入文件
s0 = temp.stream(context, addr_list=addr_list)
print(type(s0))
temp.stream(context, addr_list=addr_list).dump('addr_list_v-1.h')
实例:
import sys
import os
import jinja2
from time import ctime
import openpyxl
import pandas as pd
import numpy as np
import re
## ------------------------导入xlsx参数------------------------
module_name = 'CTL_REG' #sys.argv[1]
input_file = r'D:\Python\test.xlsx' #sys.argv[2]
input_dir = os.path.dirname(input_file)
df = pd.read_excel(input_file, sheet_name='Sheet1', skiprows=0)
## ----------------------jinja2处理---------------------------
from jinja2 import PackageLoader, Environment, FileSystemLoader
## DdataFrame 传入多个参数
addr_list = zip(df['Addr'], df['Mask'], df['Default'])
##for (i,j,k) in addr_list:
## print(i, j, k)
## 定义特定字典参数
context = {
'time': ctime(),
'module_name': 'CTL_REG'
}
#### PackageLoader 方法
##env = Environment(loader=PackageLoader('mypackage', 'templates'))
## FileSystemLoader 用法
path_dir = r'D:\Python\jinja2\templates' ## 设置templates所在的路径
loader = FileSystemLoader(path_dir)
env = Environment(loader=loader) ## 加载env类对象
temp = env.get_template('temp_0.txt') ## 选择模板
## render 方法
## s-1 = temp.render(context, addr_list=addr_list) ## render渲染方法, 生成字符串, 不能使用dump方法
## print(type(s-1))
## ## 保存基于模板生成的文件
## with open(os.path.join(path_dir,'..','ddr_addr.h'), 'w') as o_file:
## o_file.write(s-1)
## stream 方法, 生成TemplateStream, 可使用dump方法将整个流写入文件
s0 = temp.stream(context, addr_list=addr_list)
print(type(s0))
temp.stream(context, addr_list=addr_list).dump('addr_list_v-1.h')
>>>>
//-- Date: Mon Feb 21 15:59:05 2022
//-- 以下以CTL_REG 为例:
addr = 0x0, mask = 0xf03ffff, default = 0xf030000
addr = 0x4, mask = 0xffc37fff, default = 0x204068fa
addr = 0x8, mask = 0xffffffff, default = 0x81000f0f
addr = 0xc, mask = 0xffffffff, default = 0x550f0f0f
addr = 0x10, mask = 0xffffffff, default = 0xf0f0f0f
......
参考:
http://www.ainoob.cn/docs/jinja2/index.html
本文来自博客园,作者:Thisway2014,转载请注明原文链接:https://www.cnblogs.com/thisway2014/p/15912695.html