Python运维(五)--Jinja2、word模板及Excel
目录
- 一、Jinja2
- 1.1 概述
- 1.2 语法
- 1.2.1 变量
- 1.2.2 控制循环结构
- 1.2.3 宏
- 1.3 空行
- 1.3.1 分析
- 1.3.2 解决方案
- 1.4 渲染
- 1.4.1 渲染函数
- 1.4.2 继承和super函数
- 二、word模板
- 2.1 渲染函数
- 2.2 表格
- 2.2.1 动态水平合并
- 2.2.2 动态垂直合并
- 2.3 插入图片
- 三、Excel操作
- 3.1 概述
- 3.2 工作簿对象Wrokbook
- 3.3 表单对象Worksheet
- 3.3.1 表单对象属性
- 3.3.2 遍历表格
- 3.4 单元格对象Cell
一、Jinja2
1.1 概述
- 模板系统:模板文件中放置特定的占位符、占位语句,python程序文件用变量值来替换模板文件中的占位符
- Jinja2:由flask作者开发的一款模板语言,原始目的为了web网页开发
- 安装:
pip3 install Jinja2
1.2 语法
- 语法种类:注释:
{# #}
,变量取值:{{ }}
,控制结构:{% %}
- 在Jinja2渲染:传送门,以下语句可在其测试
- 一个不错的Jinja2博客:传送门
1.2.1 变量
- 代码示例
{# 这里是注释的写法,文件名index.html #} <p> 来自字典的值:{{ mydict['one'] }}</p> <p> 来自列表的值:{{ mylist[0] }}</p> <p> 来自对象方法的值:{{ myobj.meth() }}</p>
注意:大括号内两侧的空格是必须的
- 过滤器表
过滤器名 说明 safe 渲染时不转意 upper、lower、capital 把值全转大写、小写、首字母大写 title 每个单词首字母大写 trim 去首位空格 join 拼接多个值为字符串 replace 替换字符串值 round、int 对数字四舍五入、值转成整型 - 用法
{{ 11.1 | round | int }} >>> 11 {{ "hello world" | replace("hello", "goodbye") | upper }} >>> GOODBYE WORLD # names为列表:拼接字符为- {{ names | join("-") }} # 选列表第一个元素去除两侧空 {{ [' a b'] | first | trim }} >>> a b # 在给定宽度内将字符串行居中对齐 {{ '居中标题' | center }} # hosts为列表,添加换行符 {{ hosts | join('\n') }} # 添加默认值 {{ name | default('duke') }} # 默认按键对字典排序:按值排序写法dictsort(by='value') {% for key, value in dic | dictsort %} # 先管道转换,再比较 {% if str_value | float >= 4.22 %}
注:过滤器通过管道符与变量连接
1.2.2 控制循环结构
- if语句
{% if duke.sick %}duke is sick {% elif duke.dead %}duke is dead {% else %}duke is ok {% endif %}
比较运算符:==, !=, >, >=, <, <=
逻辑运算符:and, or, not - for语句
{# 遍历列表:语句排版,按没语句块考虑效果 #} <ul> {% for user in users %}<li>{{ user }}</li> {% endfor %} </ul>{# 遍历字典 #} <ul> {% for key, value in users.items() %}{% if loop.first %}<li>这是首轮循环</li> {% endif %} <li>当前键为:{{ key }}</li> <li>当前值为:{{ value }}</li> {% endfor %} </ul>
loop.index:从1开始记录循环次数,loop.index()为从0开始
loop.first:若为第一次迭代则为True,配合if使用,loop.last
loop.length:循环次数 - for + if语句:
{% for num in nums if num>10 %}
1.2.3 宏
- 定义位置:建议集中写在模板的尾部
- 宏定义
{% macro input(name, age=18) -%} <h1>{{ name }}:{{ age }}</h1> {%- endmacro -%}
- 宏使用
<h1>{{input('duke', 12)}}</h1>
1.3 空行
1.3.1 分析
- 示例
- 显示:右侧渲染结果有多处空行
- 原因分析:渲染模板时,所有语言块都将被删除,但所有空都保留在原处。也就是说,如果在块之前或之后有空格、制表符或换行符,都保留
1.3.2 解决方案
- 方法一:
- -语句:
{%- 语句 %}
,去除语言块之前的空,{% 语句 -%}
,去除之后的空(含换行符) - 渲染if语句:删除
{% if true %}
语句块,末尾换行符保留;删除{% if false %}
语句块,末尾换行符也删除;删除{% endif %}
语句块,不管真假,都保留前后空及换行符
- -语句:
- 方法二:
- 启用渲染选项:删除空行trim_blocks,删除块左侧空lstrip_blocks
- 补充选项:Strict check,若有值未传则报错
1.4 渲染
1.4.1 渲染函数
- /root/main/main.py
#!/usr/bin/python # -*- codinig: UTF-8 -*-import os import sys import jinja2# 定义模板渲染函数:模板路径,填充数据以json格式 def render(tpl_path='index.html', **kwargs):# 拆分路径:路径与文件名path, filename = os.path.split(tpl_path)# 渲染后的文件内容:模板父文件夹路径,模板文件名,传入字典return jinja2.Environment(loader=jinja2.FileSystemLoader(path or './'),trim_blocks=True,lstrip_blocks=True).get_template(filename).render(**kwargs)# 命令行操作函数 def cmd_format(**data):# 获取命令行参数列表filepath = sys.argv# 若未输入参数就通过if语句用默认模板filepath.append('')if filepath[1]:out = render(filepath[1], **data)print(out)else:out = render(**data)print(out)if __name__ == '__main__':# 数据填充字典:json格式datainput = {'head': "这是标题",'context': "这是内容"}# 这里是命令行方式,也可以直接调用render函数cmd_format(**datainput)
- 模板/root/main/index.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>{{ head }}</title> </head> <body><div><h1>{{ context }}</h1></div> </body> </html>
- 运行
python3 main.py
- 终端输出
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>这是标题</title> </head> <body><div><h1>这是内容</h1></div> </body> </html>
1.4.2 继承和super函数
- 模板继承:父模板中留
block语句块
,子模板继承父模板,并只需要写block语句块
即可 - super函数:父模板中
block语句块
中的语句,在子模板中用{{ super() }}
语句可拿到,否则子覆盖父 - /root/main/index.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body><h1>欢迎</h1><h2>以下是块内容</h2>{% block content %}<h3>这是块内的语句</h3>{%- endblock %}<h2>再见</h2> </body> </html>
- /root/main/login.html
{% extends "index.html" %}{% block content %} {{ super() }}<form>用户名:<input type="text" name="user">密码:<input type="text" name="pwd"></form> {% endblock %}
- 运行
python3 main.py login.html
- 终端输出
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body><h1>欢迎</h1><h2>以下是内容</h2> <h3>这是块内的语句</h3> <form>用户名:<input type="text" name="user">密码:<input type="text" name="pwd"></form> <h2>再见</h2> </body> </html>
二、word模板
- docxtpl模块:使用Jinja2思路,以docx为word模板
- docxtpl 主要依赖两个包:python-docx 用来读写word,jinja2用来管理插入到模板中的标签
- 官方文档:传送门
- 语法种类:注释:
{#p #}
,变量取值:{{ }}
(转义{{ variable|e }}
),控制结构:{%p %}
,p代表段落,否则会出现1.3节的空行现象,注释和控制结构每行只能出现一个,灵活运用1.3.1方法一
连接长句子 - 安装:
pip3 install docxtpl
2.1 渲染函数
/root/main/main.py
#!/usr/bin/python # -*- codinig: UTF-8 -*-from docxtpl import DocxTemplate import sys import jinja2# 定义模板渲染函数:模板路径,输出路径,填充数据以字典格式 def render(tpl_path='index.docx', output='sample.docx', **kwargs):tpl = DocxTemplate(tpl_path)# 添加参数:清除空行jinja_env = jinja2.Environment(trim_blocks=True, lstrip_blocks=True)# 渲染函数:传入数据、jinja2环境变量tpl.render(kwargs, jinja_env)tpl.save(output)print("completed")# 命令行构造函数 def cmd_format(**data):filepath = sys.argv# 保证有三个参数:防止少于两个参数的话报错filepath.append('')filepath.append('')# 指定:模版文件路径、输出文件路径(路径必须存在,否则报错)if filepath[1] and filepath[2]:render(filepath[1], filepath[2], **data)# 指定:模版文件路径、输出文件为./sample.docxelif filepath[1]:render(filepath[1], **data)# 默认:模版文件./index.docx、输出文件为./sample.docxelse:render(**data)if __name__ == '__main__':# 数据填充字典:json格式datainput = {'head': "内容",'context': "context内容"}# 这里是命令行方式,也可以直接调用render函数cmd_format(**datainput)
模版:/root/main/index.docx
运行
python3 main.py
输出:/root/main/sample.docx
2.2 表格
- 模版/root/main/index.docx
2.2.1 动态水平合并
- 模版写法
{%tc for col in context %} {% hm %}标题 {%tc endfor %} {%tc for col in context %} {{col}} {%tc endfor %} hm:水平动态合并,如下图效果
- 效果
context:[‘a’, ‘b’, ‘c’]
2.2.2 动态垂直合并
- 模版写法
{%tr for row in context %} {% vm %}竖标题 {{row}} {%tr endfor %} hm:水平动态合并,如下图效果
- 效果
2.3 插入图片
- 模版:/root/main/index.docx
{{ title_pic1 }} {{ title_pic2 }} {{ title_pic3 }}
- 渲染函数
#!/usr/bin/python # -*- codinig: UTF-8 -*-import sys import jinja2 from docxtpl import DocxTemplate, InlineImage from docx.shared import Mm, Pt# 定义模板渲染函数:模板路径,输出路径,填充数据以字典格式 def render(tpl_path='index.docx', output='sample.docx', **kwargs):tpl = DocxTemplate(tpl_path)# 添加参数:清除空行jinja_env = jinja2.Environment(trim_blocks=True, lstrip_blocks=True)# 展开image项的每个子项,重新添加进kwargsif 'images' in kwargs:for pic in kwargs['images']:width = pic.get('width')height = pic.get('height')if width and height:# 给数据字典增加项:图片的单位是像素(Pt)、毫米(Mm)kwargs.setdefault(pic.get('name'), InlineImage(tpl, pic.get('path'), width=Pt(width), height=Pt(height)))elif width:kwargs.setdefault(pic.get('name'), InlineImage(tpl, pic.get('path'), width=Pt(width)))else:kwargs.setdefault(pic.get('name'), InlineImage(tpl, pic.get('path'), height=Pt(height)))del kwargs['images']# 渲染函数:传入数据、jinja2环境变量tpl.render(kwargs, jinja_env)tpl.save(output)print("completed")# 命令行构造函数 def cmd_format(**data):filepath = sys.argv# 保证有三个参数:防止少于两个参数的话报错filepath.append('')filepath.append('')# 指定:模版文件路径、输出文件路径(路径必须存在,否则报错)if filepath[1] and filepath[2]:render(filepath[1], filepath[2], **data)# 指定:模版文件路径、输出文件为./sample.docxelif filepath[1]:render(filepath[1], **data)# 默认:模版文件./index.docx、输出文件为./sample.docxelse:render(**data)if __name__ == '__main__':# 数据填充字典:json格式datainput = {# 若没有内插图像,则删掉此项,不可为空,否则报错'images': [# 1、指定宽,2、指定高,3、指定宽高{'name': 'title_pic1', 'path': 'pic/test.png', 'height': 100},{'name': 'title_pic2', 'path': 'pic/test.png', 'width': 100},{'name': 'title_pic3', 'path': 'pic/test.png', 'width': 100, 'height': 100}]}# 这里是命令行方式,也可以直接调用render函数cmd_format(**datainput)
- 效果
三、Excel操作
3.1 概述
- openpyxl:一个读写Excel的python库,安装
pip3 install openpyxl
- 层级
- Workbook:对工作薄(Excel文件)对象的抽象
- Worksheet:对表单对象的抽象
- Cell:对单元格对象的抽象
- 操作工作簿
3.2 工作簿对象Wrokbook
- 新建空Excel
import openpyxl # 创建工作簿对象 wb = openpyxl.Workbook() ... # 保存工作簿对象 wb.save("新建表格.xlsx")
- 打开已存在Excel
import openpyxl # 打开已存在的Excel文件并返回工作簿对象 wb = openpyxl.load_workbook("新建表格.xlsx") ... wb.save("新建表格.xlsx")
- workbook对象属性
写法 解释 wb.read_only 判断文件是否以只读打开,返回布尔值 wb.encoding 返回文件编码方式,如’utf-8’ wb.properties 返回文档元数据对象,如作者、创建时间、版本…
改写wb.properties.version = 1.0
- 操作Worksheet方法
# 增表单:第二个参数为插入索引值,可选 In [1]: wb.create_sheet('boss') Out[1]: <Worksheet "boss">################################################### # 删表单:方法一,若不存在,报错KeyError In [2]: wb.remove(wb['boss']) # 方法二:del wb['boss'],若不存在,报错KeyError################################################### # 查表单:获取表单名称列表 In [3]: wb.sheetnames Out[3]: ['student', 'teacher'] # 获取表单对象:以名称方式 In [4]: wb["student"] Out[4]: <Worksheet "student"> # 获取当前活动表单对象 In [5]: wb.active Out[5]: <Worksheet "student">
3.3 表单对象Worksheet
3.3.1 表单对象属性
- 表单对象属性
写法 解释 wb.title 表格标题字符串,例如 'student'
wb.dimensions 返回表格中含有数据的表格大小,例如 'A1:D4'
ws.max_row 返回含数据的最大行数 4
,还有min_row,max_column,min_column
3.3.2 遍历表格
- 按行遍历cell对象:按列columns同
In [1]: for row in ws.rows:...: print(row) # row为每行cell对象的元组,rows为生成器 (<Cell 'student'.A1>, <Cell 'student'.B1>, <Cell 'student'.C1>, <Cell 'student'.D1>) (<Cell 'student'.A2>, <Cell 'student'.B2>, <Cell 'student'.C2>, <Cell 'student'.D2>) (<Cell 'student'.A3>, <Cell 'student'.B3>, <Cell 'student'.C3>, <Cell 'student'.D3>) (<Cell 'student'.A4>, <Cell 'student'.B4>, <Cell 'student'.C4>, <Cell 'student'.D4>)
- 按行遍历值
In [2]: for row in ws.values:...: print(row) # row为每行数据的元组,values为生成器 ('no', 'name', 'chinese', 'math') (1, 'duke', 97, 88) (2, 'park', 95, 89) (3, 'sam', 96, 87)
- 限定范围按行遍历cell对象,iter_rows迭代器
In [3]: for row in ws.iter_rows(min_row=2,max_row=3,min_col=2,max_col=3):...: print(row) # row为限定数据 (<Cell 'student'.B2>, <Cell 'student'.C2>) (<Cell 'student'.B3>, <Cell 'student'.C3>)
3.4 单元格对象Cell
- 单元格对象属性
写法 解释 ws[‘B2’] 获取cell对象,例如<Cell ‘student’.B2>, ws(row=2, column=2)
效果同cell.row 获取行数 2
,cell.column获取列数cell.value 获取单元格值 'duke'
cell.coordinate 获取单元格坐标 'B2'
- 通过cell对象获取值
In [1]: for row in ws.rows:...: scores = [cell.value for cell in row]...: print(scores) # 跟3.3.2节按行遍历值对比 ['no', 'name', 'chinese', 'math'] [1, 'duke', 97, 88] [2, 'park', 95, 89] [3, 'sam', 96, 87]
- 工作簿到单元格数据
In [1]: wb = openpyxl.load_workbook("新建表格.xlsx") # 链式获取与修改 In [2]: wb['student'].cell(row=2,column=2).value='jack' # 有数据的表格尾部追加 In [3]: unit = [4, 'smith', 93, 90] In [4]: wb['student'].append(unit) # 将更改保存到文件 In [5]: wb.save("新建表格.xlsx")
回到总目录
Python运维(五)--Jinja2、word模板及Excel相关推荐
- python运维系统开发_Python系统运维开发实战
课程主题: Python 高级运维开发实战 课程讲师: Alex 老师, triaquae python 开源运维管理软件创始人,知名 IT 公司运维开发架构师 课程安排: 每周六一天全天(早 9:0 ...
- Python运维(七)--自动化部署工具Ansible
目录 一.概述 二. 安装 2.1 控制端 2.2 被控制端 2.3 连接测试(控制端) 三.Inventory管理 3.1 简介 3.2 命令 3.3 服务器匹配 3.4 Inventory行为参数 ...
- python运维必须会用的库
python运维必须会用的库: 1 os,pathlib(系统操作库) 2 logging(运维用到的核心库,用于快速写入日志,非常好用) 3 pymysql,pymssql, ...
- python运维看什么书_学习Python在Linux运维上的应用应该看哪些书 什么样的学习路线...
匿名用户 1级 2017-08-02 回答 Python岗位有哪些呢?主要的岗位有这些: Python全栈开发工程师(10k-20K) Python运维开发工程师(15k-20K) Python高级开 ...
- python运维脚本面试_运维开发工程师 面试题 shell编程
1. 32位随机密码生成 cat /proc/sys/kernel/random/uuid | tr -d '-' 2.查看当前系统每个ip的tcp连接数 -n 强制显示IP地址 -t 显示TCP连接 ...
- python运维实战--跨堡垒机连接二级服务器上传文件
python运维实战--跨堡垒机连接二级服务器上传文件 paramiko的有关概念和操作 Welcome to Paramiko! - Paramiko documentation 这个python脚 ...
- 一群热爱python运维的精英们!
老男孩python运维开发精品培训第三期一部分学员毕业合影留念! 转载于:https://blog.51cto.com/oldboy/1363274
- python运维开发之socket网络编程01
python运维开发之socket网络编程01说明:本文来自来自北京老男孩linux运维实战培训中心-运维开发课程免费视频内容,本文内容为系列内容,更多分享信息见:http://oldboy.blog ...
- python运维之轻松模拟开发FTP软件05
以往众多运维者,大多都是在应用国外已经开发好的软件,如今的国内运维职位已经要求我们具备较强的创新能力,一些日常小工具小软件应该能做到手到拈来,这样我们才能在激烈的竞争中占据有利位置.请看: py ...
- python程序员需要掌握哪些技术-python运维要掌握哪些内容
python运维需要会什么 随着移动互联网的普及,服务器运维所面临的挑战也随之越来越大.当规模增长到一定程度,手动管理方式已经无法应对,自动化运维成为解决问题的银弹. Python凭借其灵活性,在自动 ...
最新文章
- Image Watch的使用示例
- Java 泛型 super extends 边界
- 创建一个storageevent事件_事件循环:微任务和宏任务
- 优秀HTML5网站学习范例:从“饥饿游戏浏览器”谈用户体验
- 海贼王革命家—龙—实力到底如何?
- python 第三方模块之 APScheduler - 定时任务
- 一名创业者浴火涅磐的自白——对话阿里云MVP孙琦
- python标准库使用教程_Python标准库概览
- vue父子组件传值之异步之后子组件无法拿到父组件传的值
- [论文笔记]RoBERTa: A Robustly Optimized BERT Pretraining Approach
- 适配器模式之解释器模式
- 软件需求说明书/ 概要设计说明书/项目开发计划/详细设计说明书模版(说明要点及要点解释)
- jsp连接mysql 菜鸟_在JSP中访问数据库大全
- linux下用套接字抓arp包,TCP抓包-linux
- python三维地质建模_GemPy三维地质建模工具包
- 外链式样式表_WEB前端 CSS样式表
- pdf转换工具有哪些?试一试这几个方法!
- Clickhouse外部储存表引擎(HDFS、MySQL、JDBC、Kafka、File)
- HTML网页下,在div标签中嵌套其他html页面
- 关于DM36x IPNC中IRCUT的使用
热门文章
- excel数据拆分如何快速做?
- 基于emq x开源版实现服务重启后主题和消息恢复的完整方案
- 【微博SDK调用逻辑】微博SDK的调用逻辑,最好自己还是写一个例子,试一下!!!...
- vue - vue3与vue2.x的区别(一) :目录结构不一致
- zabbix-agent2监控redis、mongodb
- python实现数组键值排序
- matlab画图,常用线条样式,导出高清图
- 聊聊一道简单的javascript面试题
- 吉利星瑞噪音分贝测试软件,吉利星瑞性能测试:确实是最好的自主A级车
- 3DMAX和MAYA,你还在纠结选择哪个吗?为什么不看这里的标准答案?