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中,存在三种语法:

    1. 控制结构 {% %}
    2. 变量取值 {{ }}
    3. 注释 {# #}
  • 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

https://blog.csdn.net/wudizuishuai/article/details/82528446

https://www.cnblogs.com/dachenzi/p/8242713.html

posted @ 2022-02-19 15:25  Thisway2014  阅读(586)  评论(0编辑  收藏  举报