pyecharts源码解读(9)渲染包render之engine模块:渲染引擎

当前pyecharts版本为1.9.0

概述

render包结构

render包位于pyecharts包顶级目录中,用于渲染图表。render包结构如下:

├─render # 渲染设置包
│  │  display.py # 定义HTML、JavaScript显示类,用于支持在notebook中嵌入输出结果
│  │  engine.py # 定义渲染相关类、函数
│  │  snapshot.py # 定义渲染图片函数
│  │  __init__.py # 暴露渲染图片函数
│  │
│  ├─templates # 定义渲染模板
│  │      components.html
│  │      macro
│  │      nb_components.html
│  │      nb_jupyter_globe.html
│  │      nb_jupyter_lab.html
│  │      nb_jupyter_lab_tab.html
│  │      nb_jupyter_notebook.html
│  │      nb_jupyter_notebook_tab.html
│  │      nb_nteract.html
│  │      simple_chart.html
│  │      simple_globe.html
│  │      simple_page.html
│  │      simple_tab.html

engine模块

engine模块,路径为pyecharts/render/engine.py,作用为提供渲染接口(HTML和notebook)。

engine模块的结构如下图所示。

  • write_utf8_html_file(file_name: str, html_content: str)函数:根据HTML字符串生成HTML文件。
  • RenderEngine(env: Optional[Environment] = None)类:根据jinja2的环境变量提供渲染抽象接口。
  • render(chart, path: str, template_name: str, env: Optional[Environment], **kwargs) -> str函数:封装RenderEngine(env: Optional[Environment] = None)render_chart_to_file方法输出HTML文件。返回值为输出的HTML文件的路径。
  • render_embed(chart, template_name: str, env: Optional[Environment], **kwargs) -> str函数:封装RenderEngine(env: Optional[Environment] = None)render_chart_to_template方法输出HTML字符串。返回值为字符串。
  • render_notebook(self, notebook_template, lab_template)函数:将图表嵌入到notebook中,针对不同notebook类型提供不同输出方式。notebook和jupyter lab封装RenderEngine(env: Optional[Environment] = None)render_chart_to_notebook方法实现。返回值为pyecharts.render.display.HTML类对象。
  • load_javascript(chart)函数:为jupyter lab提供JavaScript支持,根据chart对象的JavaScript依赖库生成JavaScript代码。返回值为pyecharts.render.display.Javascript类对象。

在这里插入图片描述

engine模块的应用

根据图表对象基类Base的源码可知,图表类的渲染方法底层底层由engine模块的相应类、函数实现。

pyecharts/charts/base.py模块源码

from ..render import engine

class Base(ChartMixin):
    """
    `Base` is the root class for all graphical class, it provides
    part of the initialization parameters and common methods
    """

    def __init__(self, init_opts: Union[InitOpts, dict] = InitOpts()):
        _opts = init_opts
        if isinstance(init_opts, InitOpts):
            _opts = init_opts.opts

    def render(
        self,
        path: str = "render.html",
        template_name: str = "simple_chart.html",
        env: Optional[Environment] = None,
        **kwargs,
    ) -> str:
        self._prepare_render()
        return engine.render(self, path, template_name, env, **kwargs)

    def render_embed(
        self,
        template_name: str = "simple_chart.html",
        env: Optional[Environment] = None,
        **kwargs,
    ) -> str:
        self._prepare_render()
        return engine.render_embed(self, template_name, env, **kwargs)

    def render_notebook(self):
        self.chart_id = uuid.uuid4().hex
        self._prepare_render()
        return engine.render_notebook(
            self, "nb_jupyter_notebook.html", "nb_jupyter_lab.html"
        )

pyecharts/render/engine.py模块源码

import os
from collections import Iterable

from jinja2 import Environment

from ..commons import utils
from ..datasets import EXTRA, FILENAMES
from ..globals import CurrentConfig, NotebookType
from ..types import Any, Optional
from .display import HTML, Javascript


def write_utf8_html_file(file_name: str, html_content: str):
    with open(file_name, "w+", encoding="utf-8") as html_file:
        html_file.write(html_content)


class RenderEngine:
    def __init__(self, env: Optional[Environment] = None):
        self.env = env or CurrentConfig.GLOBAL_ENV

    @staticmethod
    def generate_js_link(chart: Any) -> Any:
        if not chart.js_host:
            chart.js_host = CurrentConfig.ONLINE_HOST
        links = []
        for dep in chart.js_dependencies.items:
            # TODO: if?
            if dep.startswith("https://api.map.baidu.com"):
                links.append(dep)
            if dep in FILENAMES:
                f, ext = FILENAMES[dep]
                links.append("{}{}.{}".format(chart.js_host, f, ext))
            else:
                for url, files in EXTRA.items():
                    if dep in files:
                        f, ext = files[dep]
                        links.append("{}{}.{}".format(url, f, ext))
                        break
        chart.dependencies = links
        return chart

    def render_chart_to_file(self, template_name: str, chart: Any, path: str, **kwargs):
        """
        Render a chart or page to local html files.

        :param chart: A Chart or Page object
        :param path: The destination file which the html code write to
        :param template_name: The name of template file.
        """
        tpl = self.env.get_template(template_name)
        html = utils.replace_placeholder(
            tpl.render(chart=self.generate_js_link(chart), **kwargs)
        )
        write_utf8_html_file(path, html)

    def render_chart_to_template(self, template_name: str, chart: Any, **kwargs) -> str:
        tpl = self.env.get_template(template_name)
        return utils.replace_placeholder(
            tpl.render(chart=self.generate_js_link(chart), **kwargs)
        )

    def render_chart_to_notebook(self, template_name: str, **kwargs) -> str:
        tpl = self.env.get_template(template_name)
        return utils.replace_placeholder(tpl.render(**kwargs))


def render(
    chart, path: str, template_name: str, env: Optional[Environment], **kwargs
) -> str:
    RenderEngine(env).render_chart_to_file(
        template_name=template_name, chart=chart, path=path, **kwargs
    )
    return os.path.abspath(path)


def render_embed(
    chart, template_name: str, env: Optional[Environment], **kwargs
) -> str:
    return RenderEngine(env).render_chart_to_template(
        template_name=template_name, chart=chart, **kwargs
    )


def render_notebook(self, notebook_template, lab_template):
    instance = self if isinstance(self, Iterable) else (self,)
    if CurrentConfig.NOTEBOOK_TYPE == NotebookType.JUPYTER_NOTEBOOK:
        require_config = utils.produce_require_dict(self.js_dependencies, self.js_host)
        return HTML(
            RenderEngine().render_chart_to_notebook(
                template_name=notebook_template,
                charts=instance,
                config_items=require_config["config_items"],
                libraries=require_config["libraries"],
            )
        )

    if CurrentConfig.NOTEBOOK_TYPE == NotebookType.JUPYTER_LAB:
        return HTML(
            RenderEngine().render_chart_to_notebook(
                template_name=lab_template, charts=instance
            )
        )

    if CurrentConfig.NOTEBOOK_TYPE == NotebookType.NTERACT:
        return HTML(self.render_embed())

    if CurrentConfig.NOTEBOOK_TYPE == NotebookType.ZEPPELIN:
        print("%html " + self.render_embed())


def load_javascript(chart):
    scripts = []
    for dep in chart.js_dependencies.items:
        f, ext = FILENAMES[dep]
        scripts.append("{}{}.{}".format(CurrentConfig.ONLINE_HOST, f, ext))
    return Javascript(lib=scripts)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值