Jupyter循环使用ipysankeywidget保存Sankey图为PNG报错问询
ipysankeywidget循环导出PNG失败解决方案
问题根源
ipysankeywidget属于前端渲染类组件,图片生成逻辑完全在浏览器侧执行:仅在Python后端实例化Sankey对象不会触发前端渲染流程,也就不会生成对应的图片数据,调用save_png()时自然拿不到内容报错。逐行运行时notebook会自动渲染返回的Sankey对象,前端生成图片数据后后端就能正常调用保存接口。
解决方案
方案1:使用auto_save_png+显式触发渲染(官方推荐)
直接在实例化SankeyWidget时指定自动保存路径,同时通过display方法手动触发每个对象的前端渲染,不需要额外调用save_png(),修改后代码如下:
from ipywidgets import Layout from ipysankeywidget import SankeyWidget from IPython.display import display, clear_output import time def draw_one(use_case, limit=50): df = Cli.query_paths(use_case=use_case, limit=limit) layout = Layout(width="2000", height="500") fpath = f'./data/ignored/images/{use_case}-{limit}.png' # 实例化时指定auto_save_png参数 sankey = SankeyWidget( links=df.to_dict('records'), layout=layout, auto_save_png=fpath ) # 手动触发渲染 display(sankey) # 给前端预留渲染时间,复杂图表可适当调大数值 time.sleep(2) # 可选:清除页面上的图表展示,避免堆积 clear_output(wait=True) return sankey cases = [ 'INTL', 'PAC', ] def loop(): for use_case in cases: print('sk:', use_case) sk = draw_one(use_case, limit=50) loop()
方案2:SVG转PNG(不依赖前端实时渲染)
如果不想依赖浏览器渲染逻辑,批量导出更稳定,可以先导出SVG格式,再用第三方库转成PNG:
# 先安装依赖:pip install cairosvg from ipywidgets import Layout from ipysankeywidget import SankeyWidget import cairosvg import os def draw_one(use_case, limit=50): df = Cli.query_paths(use_case=use_case, limit=limit) layout = Layout(width="2000", height="500") svg_path = f'./data/ignored/images/{use_case}-{limit}.svg' png_path = f'./data/ignored/images/{use_case}-{limit}.png' sankey = SankeyWidget(links=df.to_dict('records'), layout=layout) # 先保存SVG sankey.save_svg(svg_path) # SVG转PNG cairosvg.svg2png(url=svg_path, write_to=png_path, scale=2) # scale参数控制PNG清晰度 # 可选:删除临时SVG文件 os.remove(svg_path) cases = [ 'INTL', 'PAC', ] def loop(): for use_case in cases: print('sk:', use_case) sk = draw_one(use_case, limit=50) loop()
内容的提问来源于stack exchange,提问作者dcsan
相关产品推荐
相关产品推荐

