From 1c0d3b0e3a8c5a7f10cadf8e6246454413394c9d Mon Sep 17 00:00:00 2001 From: Elwynn Chen Date: Wed, 21 May 2025 01:52:35 +0800 Subject: [PATCH] Add programmatic export API --- README.md | 12 ++++++++++++ pygwalker/api/pygwalker.py | 22 ++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3495934..e21f263 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,18 @@ walker = pyg.walk( * [Use PyGWalker in Kaggle](https://www.kaggle.com/code/lxy21495892/airbnb-eda-pygwalker-demo) * [Use PyGWalker in Google Colab](https://colab.research.google.com/drive/171QUQeq-uTLgSj1u-P9DQig7Md1kpXQ2?usp=sharing) +### Programmatic Export of Charts + +After saving a chart from the UI, you can retrieve the image directly from Python. + +```python +walker = pyg.walk(df, spec="./chart_meta_0.json") +# edit the chart in the UI and click the save button +walker.save_chart_to_file("Chart 1", "chart1.svg", save_type="svg") +png_bytes = walker.export_chart_png("Chart 1") +svg_bytes = walker.export_chart_svg("Chart 1") +``` + ## Use pygwalker in Streamlit Streamlit allows you to host a web version of pygwalker without figuring out details of how web application works. diff --git a/pygwalker/api/pygwalker.py b/pygwalker/api/pygwalker.py index cbe92e6..8731699 100644 --- a/pygwalker/api/pygwalker.py +++ b/pygwalker/api/pygwalker.py @@ -274,7 +274,7 @@ def chart_list(self) -> List[str]: """ return list(self._chart_map.keys()) - def save_chart_to_file(self, chart_name: str, path: str, save_type: Literal["html", "png"] = "png"): + def save_chart_to_file(self, chart_name: str, path: str, save_type: Literal["html", "png", "svg"] = "png"): """ Save the chart to a file. """ @@ -286,8 +286,12 @@ def save_chart_to_file(self, chart_name: str, path: str, save_type: Literal["htm content = self.export_chart_png(chart_name) write_mode = "wb" encoding = None + elif save_type == "svg": + content = self.export_chart_svg(chart_name) + write_mode = "wb" + encoding = None else: - raise ValueError(f"save_type must be html or png, but got {save_type}") + raise ValueError(f"save_type must be html, png or svg, but got {save_type}") with open(path, write_mode, encoding=encoding) as f: f.write(content) @@ -311,6 +315,20 @@ def export_chart_png(self, chart_name: str) -> bytes: with urllib.request.urlopen(chart_data.single_chart) as png_string: return png_string.read() + def export_chart_svg(self, chart_name: str) -> bytes: + """Export the chart as svg bytes.""" + chart_data = self._get_chart_by_name(chart_name) + if len(chart_data.charts) == 0: + raise ValueError(f"chart_name: {chart_name} has no svg data") + svg_str = chart_data.charts[0].data + prefix = "data:image/svg+xml;base64," + if isinstance(svg_str, str) and svg_str.startswith(prefix): + import base64 + return base64.b64decode(svg_str[len(prefix):]) + if isinstance(svg_str, str): + return svg_str.encode("utf-8") + return svg_str + def display_chart(self, chart_name: str, *, title: Optional[str] = None, desc: str = ""): """ Display the chart in the notebook.