一种pyecharts离线加载图表方法

环境

windows11 python-3.10.5 pyecharts-2.0.3,其他版本没试过。

需求

之前用0.5版本的pyecharts倒是没遇到离线使用的问题。换了v2版本后遇到了。

网上查到的大多数方法是开个http服务器,让浏览器访问生成图表的html时下载js脚本改为从本地服务器下载,从而解决pyecharts离线使用问题。但我的需求是:

1、不需要开服务器也能生成html图表。

2、生成的html不用再另外下载js脚本,换台电脑也能直接打开显示图表。

3、不在源码上改动,换台电脑使用一样的pyecharts也可以运行使用。

解决过程

下载js脚本

改动前,生成一份非嵌入js的图表html,找到js脚本链接,下载到本地。

浏览器访问https://assets.pyecharts.org/assets/v5/echarts.min.js,保存下js文件。

嵌入JS配置

需求2很好解决,把js代码嵌入html即可。在pyecharts手册里有提到一个渲染配置项RenderOpts,提供是否在渲染HTML时嵌入JS文件,默认False不嵌入。若想要“换台电脑也能直接打开显示图表”这个效果,则把此配置项设为True即可。

 创建图表时候,初始化时候指定下render_opts参数,如下柱状图代码:

bar = Bar(init_opts=opts.InitOpts(), render_opts=opts.RenderOpts(is_embed_js=True))

加载js代码方法重写

其实到本步骤,使用本地开服务器方式+嵌入js到html方法,也能勉强满足我原始的需求,但是运行时候发现了个问题,我是用http方式开的服务,但是嵌入js脚本代码却是用https请求访问js资源后才去嵌入html的,导致了异常报错。修改源码把HTTPSConnection改为HTTPConnection发现可以,进一步可以取scheme进行http/https判断走不同逻辑请求。但是我并不想在源码做改动,这样我换台电脑还要改,显然挺麻烦的。

这里我想到了猴子补丁的方法,将源码里的load_javascript_contents方法替换为自己编写的方法。load_javascript_contents的逻辑延用源码的逻辑,然后补充2个点。1个是如果请求的js是echarts.min.js(别的同理),则读取本地echarts.min.js文件内容赋值,达成离线使用效果。1个是判断请求是http还是https,走不同的连接,后续如果扩展可能需要。替换方法的代码如下:

import http.client
from typing import Optional
from urllib.parse import urlparse

from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.render.display import Javascript


class ChartsLib(object):

    def __init__(self):
        Javascript.load_javascript_contents = self.load_javascript_contents

    @staticmethod
    def read_echarts_min_js():
        with open("echarts.min.js", "r", encoding="utf-8") as f:
            text = f.read()
            f.close()
        return text

    @staticmethod
    def load_javascript_contents(self):
        for lib in self.lib:
            if "echarts.min.js" in lib:
                self.javascript_contents[lib] = ChartsLib.read_echarts_min_js()
                continue
            parsed_url = urlparse(lib)
            scheme: str = parsed_url.scheme
            host: str = str(parsed_url.hostname)
            port: int = parsed_url.port
            path: str = parsed_url.path
            resp: Optional[http.client.HTTPResponse] = None
            try:
                if scheme == "https":
                    conn = http.client.HTTPSConnection(host, port)
                else:
                    conn = http.client.HTTPConnection(host, port)
                conn.request("GET", path)
                resp = conn.getresponse()
                if resp.status != 200:
                    raise RuntimeError("Cannot load JavaScript lib: %s" % lib)
                self.javascript_contents[lib] = resp.read().decode("utf-8")
            finally:
                if resp is not None:
                    resp.close()
        return self

    @staticmethod
    def demo_bar(infos, interactions, html_name="bar_interactions.html"):
        bar = Bar(init_opts=opts.InitOpts(height="1000px"), render_opts=opts.RenderOpts(is_embed_js=True))
        bar.add_xaxis(infos)
        bar.add_yaxis("xx数据", interactions)
        bar.reversal_axis()
        bar.set_series_opts(label_opts=opts.LabelOpts(position="right"))
        bar.set_global_opts(title_opts=opts.TitleOpts(title="示例表"),
                            toolbox_opts=opts.ToolboxOpts(),
                            datazoom_opts=[
                                opts.DataZoomOpts(orient="horizontal", range_start=0, range_end=100),
                                opts.DataZoomOpts(orient='vertical', range_start=0, range_end=100)
                            ])
        bar.render(html_name)
        return bar

这样就达到了3个需求点要求了。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值