https://sanic.readthedocs.io/en/latest/index.html
中文文档
https://www.osgeo.cn/sanic/
from sanic import Sanic
from sanic.blueprints import Blueprint
app = Sanic(__name__)
# Serves files from the static folder to the URL /static
app.static('/static', './static')
静态目录设置方法
Python + Pyecharts + Sanic
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
<script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
</head>
<style type="text/css">
html,
body {
width: 100%;
height: 100%;
min-width: 1200px;
min-height: 900px;
padding: 0;
margin: 0;
}
iframe{
/*宽度*/
width: 100%;
/*高度*/
height: 100%;
/*背景图片路径*/
background-image: url(img/web_background.png);
/*背景图片大小*/
background-size: 100% 100%;
}
</style>
<body>
<!--src路径 scrolling="no" 滚动条隐藏-->
<iframe src="my_test.html" scrolling="no" ></iframe>
<div id="bar" style="width:1200px; height:900px;"></div>
<script>
var chart = echarts.init(document.getElementById('bar'), 'white', {renderer: 'canvas'});
// 定时全量更新
$(
function () {
fetchData();
setInterval(fetchData, 2000);
}
);
function fetchData() {
console.log("处理中......")
$.ajax({
type: "GET",
url: "http://127.0.0.1:8900/index.html",
// dataType: 'json',
// success: function (result) {
// chart.setOption(JSON.parse(result));
// }
});
}
</script>
</body>
</html>
App.py
from pyecharts.charts import Bar, Scatter, Funnel, Liquid
from pyecharts import options as opts
# 内置主题类型可查看 pyecharts.globals.ThemeType
from pyecharts.globals import ThemeType, SymbolType
from pyecharts.charts import WordCloud
# # V1 版本开始支持链式调用
# bar = (
# Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK,width="600px",height="300px"))
# .add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子", "西服", "马卦", "秋裤", "皮鞋"])
# .add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105, 200, 100, 50, 300])
# .add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49, 120, 80, 90, 200])
# .set_global_opts(title_opts=opts.TitleOpts(title="销售情况-商家销售业绩分析"))
# )
# # render 会生成本地 HTML 文件,默认会在当前目录生成 render.html 文件
# # 也可以传入路径参数,如 bar.render("mycharts.html")
# bar.render()
from pyecharts import options as opts
from pyecharts.charts import Bar, Grid, Line
from pyecharts.faker import Faker
from pyecharts.charts import Pie, Gauge, Map, Page
from sanic import Sanic
from sanic.response import json, html
from sanic import response
# 初始化 Sanic
app = Sanic(__name__)
app.static("/", "./")
def chart_base():
bar = (
Bar(init_opts=opts.InitOpts(width="400px", height="220px", theme=ThemeType.MACARONS))
.add_xaxis(Faker.choose())
.add_yaxis("商家A", Faker.values())
.add_yaxis("商家B", Faker.values())
.set_global_opts(title_opts=opts.TitleOpts(title="数据-平台", pos_top="10px"),
legend_opts=opts.LegendOpts(pos_top="10", pos_left="150px"))
)
barA = (
Bar(init_opts=opts.InitOpts(width="400px", height="220px", theme=ThemeType.INFOGRAPHIC))
.add_xaxis(Faker.choose())
.add_yaxis("商家C", Faker.values())
.add_yaxis("商家D", Faker.values())
.set_global_opts(title_opts=opts.TitleOpts(title="数据-统计", pos_top="10px"),
legend_opts=opts.LegendOpts(pos_top="10px", pos_left="150px"))
)
line = (
Line(init_opts=opts.InitOpts(width="400px", height="220px", theme=ThemeType.WONDERLAND))
.add_xaxis(Faker.choose())
.add_yaxis("商家E", Faker.values())
.add_yaxis("商家F", Faker.values())
.set_global_opts(
title_opts=opts.TitleOpts(title="Grid-Line", pos_left="500px", pos_top="105px"),
legend_opts=opts.LegendOpts(pos_top="110px", pos_left="600px"),
)
)
lineA = (
Line(init_opts=opts.InitOpts(width="400px", height="220px", theme=ThemeType.MACARONS))
.add_xaxis(Faker.choose())
.add_yaxis("商家G", Faker.values())
.add_yaxis("商家H", Faker.values())
.set_global_opts(
title_opts=opts.TitleOpts(title="Grid-Line", pos_left="500px", pos_top="380px"),
legend_opts=opts.LegendOpts(pos_top="390px", pos_left="600px"),
)
)
lineB = (
Line(init_opts=opts.InitOpts(width="400px", height="220px", theme=ThemeType.MACARONS))
.add_xaxis(Faker.choose(), )
.add_yaxis("商家I", Faker.values())
.set_global_opts(
title_opts=opts.TitleOpts(title="Grid-Line", pos_left="500px", pos_top="380px"),
legend_opts=opts.LegendOpts(pos_top="390px", pos_left="600px")
)
)
gauge = (
Gauge(init_opts=opts.InitOpts(width="400px", height="220px", theme=ThemeType.MACARONS))
.add("", [("完成率", 66.6)], radius="100px",
title_label_opts=opts.LabelOpts(font_size=20, color="blue", font_family="Microsoft YaHei"),
)
.set_global_opts(title_opts=opts.TitleOpts(title="完成情况"),
legend_opts=opts.LegendOpts(pos_left="10px", pos_top="10px")
)
)
gaugeA = (
Gauge(init_opts=opts.InitOpts(width="400px", height="220px", theme=ThemeType.MACARONS))
.add("", [("上升率", 82.6)], radius="100px",
title_label_opts=opts.LabelOpts(font_size=20, color="blue", font_family="Microsoft YaHei"),
)
.set_global_opts(title_opts=opts.TitleOpts(title="上升情况"),
legend_opts=opts.LegendOpts(pos_left="10px", pos_top="10px")
)
)
mmap = (
Map(init_opts=opts.InitOpts(width="400px", height="220px", theme=ThemeType.MACARONS))
.add("商家A", [list(z) for z in zip(Faker.provinces, Faker.values())], "china",
is_map_symbol_show=False,
)
.set_global_opts(
title_opts=opts.TitleOpts(
title="全国数据分析",
subtitle="人口密度数据", pos_top="50px", pos_left="100px",
),
visualmap_opts=opts.VisualMapOpts(
min_=80,
max_=500,
range_text=["High", "Low"],
is_calculable=True,
),
)
)
name = [
("资源数据展示平台", "1"),
]
wd = (
WordCloud(init_opts=opts.InitOpts(width="600px", height="120px", theme=ThemeType.SHINE))
.add("", name, word_size_range=(40, 40), shape=SymbolType.DIAMOND)
)
funnel = (
Funnel(init_opts=opts.InitOpts(width="400px", height="220px", theme=ThemeType.MACARONS))
.add("商品", [list(z) for z in zip(Faker.choose(), Faker.values())])
.set_global_opts(title_opts=opts.TitleOpts(title="Funnel-基本示例"))
)
x_data = ["展现", "点击", "访问", "咨询", "订单"]
y_data = [100, 80, 60, 40, 20]
data = [[x_data[i], y_data[i]] for i in range(len(x_data))]
funnrl2 = (
Funnel(init_opts=opts.InitOpts(width="400px", height="220px"))
.add(
series_name="",
data_pair=data,
gap=2,
tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b} : {c}%"),
label_opts=opts.LabelOpts(is_show=True, position="inside"),
itemstyle_opts=opts.ItemStyleOpts(border_color="#fff", border_width=1),
)
.set_global_opts(title_opts=opts.TitleOpts(title="漏斗图", subtitle="纯属虚构"))
)
liquid = (
Liquid(init_opts=opts.InitOpts(width="400px", height="220px"))
.add("lq", [0.2], label_opts=opts.LabelOpts(
font_size=30,
position="inside",
),
)
.set_global_opts(title_opts=opts.TitleOpts(title="Liquid-基本示例"))
)
pie = (
Pie(init_opts=opts.InitOpts(width="400px", height="220px"))
.add("", [list(z) for z in zip(Faker.choose(), Faker.values())])
.set_colors(["blue", "green", "yellow", "red", "pink", "orange", "purple"])
.set_global_opts(title_opts=opts.TitleOpts(title="Pie-设置颜色"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)
# grid = (
# Grid(init_opts=opts.InitOpts(width="1440px", height="900px", page_title="标题设置-数据分析大屏展示"
# , theme=ThemeType.WONDERLAND))
# # .add(bar, grid_opts=opts.GridOpts(pos_left="60px", pos_top="140px", width="300px", height="180px"))
# # .add(line, grid_opts=opts.GridOpts(pos_left="550px", pos_top="140px", width="400px", height="220px"))
# # .add(lineB, grid_opts=opts.GridOpts(pos_left="1100px", pos_top="140px", width="300px", height="180px"))
# # .add(barA, grid_opts=opts.GridOpts(pos_left="60px", pos_top="440px", width="300px", height="180px"))
# # .add(lineA, grid_opts=opts.GridOpts(pos_left="550px", pos_top="440px", width="400px", height="220px"))
# # .add(pie, grid_opts=opts.GridOpts(pos_left="1100px", pos_top="440px"))
# .add(mmap, grid_opts=opts.GridOpts(pos_left="50px", pos_top="440px", width="5500", height="500"))
# .render("grid_vertical.html")
# )
page = Page(layout=Page.DraggablePageLayout)
page.add(bar, barA, line, lineA, lineB, mmap, gauge, gaugeA, wd, funnel, funnrl2, liquid, pie)
page.render("test.html")
# page.render("test.html")
# Page.save_resize_html("test.html",
# cfg_file="chart_config.json",
# dest="my_test.html")
return page
@app.route("/")
async def index(request):
page = chart_base()
return html(open("index.html").read())
# return json({"hello": "world"})
if __name__ == '__main__':
app.run(host="127.0.0.1", port=8900)
需要注意的地方:
app.static("/", “./”)
设置WEB所提供服务对应的目录
index.html 中调用的地址端口和WEB服务使用的端口要一致