神器Jinja2,用 Python 快速生成分析報告!
回復“書籍”即可獲贈Python從入門到進階共10本電子書
大家好,我是早起。
在之前的文章中,我們使用 Python 開發(fā)了一個簡單的基金購買策略的回測系統(tǒng)。在代碼執(zhí)行完畢后,會生成一系列的結果,包含大量圖片、表格如下
此時如果一個一個查看的話便十分低效,如果能使用一個文件把全部輸出結果都保存將會大大提高體驗。
首先想到的當然是 PDF 格式,利用 Python 操作 PDF 也是之前文章分享過很多,想必利用表格+圖片生成一個新的PDF并不困難。研究了一番后,發(fā)現(xiàn)確實不難,但是太繁瑣了,并且 PDF 涉及格式、分頁等,如果沒有調(diào)整好可能會將一張圖片放在兩頁或者一頁只有一張圖其余全是空白,十分影響美觀,由于我每次產(chǎn)生的結果并不固定,因此很難找到一個通用的模版,遂放棄。
PDF 既然不行,Word就更不用考慮了,所以只能選擇 html 格式,雖然跨平臺性沒有 PDF 好,但是勝在排版簡單,不需要考慮分頁處理。基于 Python 生成 html 有很多成熟的 web 開發(fā)框架可以選擇,但為了整體過程不太復雜,最終選擇 Jinja2 來實現(xiàn)這個需求。
02
jinja2
Jinja2 是一個 Python 的功能齊全的模板引擎,簡單來說就是我們將 html 的主要部分寫好,將需要填充的內(nèi)容空出來,這樣就是一個模版,之后就可以使用 Jinja2 來自動將模版文件填充,形成一個完整的 html 文件。
填入文字
首先我們需要制作一個最簡單的模版文件template.html,內(nèi)容如下
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>report</title>
</head>
<h1>基金策略回測報告</h1>
<body>
<h2>一、策略詳情</h2>
<p>策略描述:{{ strategy_name }}</p>
<p>回測時間段:{{ start_time }} --> {{ end_time }} </p>
<p>初始本金:{{ money }}</p>
</body>
</html>
直接打開如下
其中被 {{}} 包起來的變量,就是我們需要用 Python 傳遞給模版的,很明顯上方代碼缺少四個變量,下面是 Python 代碼
import pandas as pd
from jinja2 import Environment, FileSystemLoader
data = {'strategy_name': '第一個策略',
'start_time': '2020-01-01',
'end_time': '2021-06-01',
'money': 20000}
env = Environment(loader=FileSystemLoader('./'))
template = env.get_template('template.html')
with open("out.html", 'w+', encoding='utf-8') as f:
out = template.render(strategy_name=data['strategy_name'],
start_time=data['start_time'],
end_time=data['end_time'],
money=data['money'])
f.write(out)
f.close()
在上面的代碼中,我們使用env.get_template('template.html')讀取模版文件,并將需要需要傳入的數(shù)據(jù)寫入字典中,并將 value 通過template.render傳給模版并渲染輸出,現(xiàn)在打開生成的 out.html 內(nèi)容如下
可以看到目標位置的文字都被正確填充,當然填入文字是最基本的操作,下面繼續(xù)介紹如何自動創(chuàng)建表格。
填入表格
其實填入表格和填入文字本質(zhì)上是一樣的,只不過需要使用循環(huán)來操作,例如將回測指標匯總.xlsx添加到html中
首先在模版文件中創(chuàng)建一個表格
<h2>二、回測結果</h2>
<table border="1" width = "40%" cellspacing='0' cellpadding='0'>
<tr>
<th>基金名稱</th>
<th>總投入本金</th>
<th>總收益率</th>
<th>最大回測率</th>
</tr>
{% for item in items %}
<tr align='center'>
<td>{{ item.基金名稱 }}</td>
<td>{{ item.消耗本金 }}</td>
<td>{{ item.總收益率 }}</td>
<td>{{ item.最大回撤率 }}</td>
</tr>
{% endfor%}
</table>
在上面的代碼中,我們使用創(chuàng)建了一個table,并將表頭寫好,將 cell 內(nèi)容設置為待填充,注意在jinja2中的循環(huán)是通過{% %}來完成的。
例如{% for item in items %} 就需要我們傳入一個字典形式 items ,并且里面包含基金名稱、消耗本金、總收益率、最大回撤率四個key,此時 Python 代碼修改如下
import pandas as pd
from jinja2 import Environment, FileSystemLoader
df = pd.read_excel('回測指標匯總.xlsx')
df['消耗本金'] = df['消耗本金'].astype(str) + ' 元'
df['最大回撤率'] = df['最大回撤率'].astype(str) + '%'
df['總收益率'] = df['總收益率'].astype(str) + '%'
data = df.to_dict('records')
results = {}
results.update({'strategy_name': '第一個策略',
'start_time': '2020-01-01',
'end_time': '2021-06-01',
'money': 20000,
'items': data})
env = Environment(loader=FileSystemLoader('./'))
template = env.get_template('template.html')
with open("out.html", 'w+', encoding='utf-8') as f:
out = template.render(strategy_name=results['strategy_name'],
start_time=results['start_time'],
end_time=results['end_time'],
money=results['money'],
items = results['items'])
f.write(out)
f.close()
需要注意的是因為我們需要循環(huán)操作,所以傳入的 items 就需要是可迭代的,但又需要根據(jù)關鍵字匹配值,所以可以將每一行數(shù)據(jù)轉換為字典,并放在 list 中,這一步可以使用 pandas 讀取excel并直接使用df.to_dict('records')完成(吹一波pandas)
現(xiàn)在執(zhí)行上面的代碼,并打開輸出后的 html
可以看到,Excel的全部內(nèi)容都被正確的填入,下面介紹如何填入圖片。
填入圖片
其實 html 展示圖片就是通過<a>標簽超鏈接指向圖片地址,所以本質(zhì)上和填充文字差不多,只需要在模版文件中把本地圖片地址預留出來,之后使用 jinja2 傳入即可,例如可以在模版中添加以下內(nèi)容
<a name="{{ 回測指標 }}"> <img src="{{ indicator }}" width="850"></a>
此時在 Python 代碼中指定indicator圖片路徑并傳入即可
indicator = 'images/' + '回測指標.png'
with open("out.html", 'w+', encoding='utf-8') as f:
out = template.render(strategy_name=results['strategy_name'],
start_time=results['start_time'],
end_time=results['end_time'],
money=results['money'],
items = results['items'],
indicator = indicator)
f.write(out)
f.close()
執(zhí)行后即可正確展示圖片如下
當然我們的圖片不止一張,可以像上面插入表格一樣將圖片地址循環(huán)填入即可,本文不再贅述,感興趣讀者可以自己研究。
修改樣式
當然,默認生成的 html 樣式可能不夠好看,我們也可以進一步添加一點CSS代碼來調(diào)整,為了簡化可以直接將代碼寫在標簽中
<style type="text/css">
h1 {margin-left: 20px}
h2 {margin-left: 20px;
font-size: 19px;
font-weight: bold;
display: inline-block;
padding-left: 10px;
border-left: 5px solid #916dd5;}
h3 {margin-left: 20px}
h4 {margin-left: 20px;
margin-bottom: -5px}
table {margin-left: 20px;
margin-top: 5px;
margin-bottom: 5px}
p {margin-left: 20px}
a {margin-top: -5px;}
</style>
主要是添加了一點縮進和間距,讓結果看起來更舒服一點,現(xiàn)在自動生成的 html 文件部分如下
最后只需要將上述 Python 代碼封裝,然后在主函數(shù)運行結束后自動將相關參數(shù)進行傳遞,即可全程自動化生成 html 報告!
當然本文介紹的 Jinja2 操作只是其簡單的一個應用,更多的用法與功能感興趣的讀者可以自己查閱官方文檔。
------------------- End -------------------
往期精彩文章推薦:

歡迎大家點贊,留言,轉發(fā),轉載,感謝大家的相伴與支持
想加入Python學習群請在后臺回復【入群】
萬水千山總是情,點個【在看】行不行
/今日留言主題/
隨便說一兩句吧~~
