You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jupyter Notebook转HTML后Plotly图表数据丢失问题求助

解决Plotly多图表导出HTML后早期图表数据丢失的问题

问题原因

浏览器对同时活跃的WebGL上下文数量有严格限制(通常在16-24个之间)。你的代码生成了10个独立的Plotly折线图,保存为HTML后所有图表会同时渲染,当数量超过浏览器上限时,最早创建的WebGL上下文会被强制回收,导致对应的图表数据丢失,这就是控制台出现Too many active WebGL contexts警告的原因。

解决方案

1. 切换到SVG静态渲染模式

Plotly默认使用WebGL渲染交互式图表,改用SVG渲染可以完全避免WebGL上下文的限制,同时保持基本的交互功能(悬停、缩放等)。修改代码中图表的渲染方式即可:

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import plotly.express as px

# 创建数据帧
start_date = datetime(2018, 1, 1)
end_date = datetime(2022, 12, 31)
num_days = (end_date - start_date).days + 1
num_cols = 100
data = np.random.rand(num_days, num_cols)
dates = [start_date + timedelta(days=i) for i in range(num_days)]
df = pd.DataFrame(data, columns=[f"Column_{i+1}" for i in range(num_cols)])
df['Date'] = dates

x = 10
while x < len(df.columns):
    columns_to_plot = df.columns[x-10:x].tolist()
    fig = px.line(df, x=df['Date'], y=columns_to_plot)
    # 使用SVG渲染器替代默认WebGL
    fig.show(renderer="svg")
    x += 10

如果需要批量导出HTML,也可以在保存时指定SVG格式:

# 保存单个图表为SVG模式的HTML
fig.write_html("chart.html", full_html=True, include_plotlyjs='cdn', renderer="svg")

2. 合并图表减少WebGL上下文数量

将多个折线图合并到同一个画布的子图中,大幅减少独立图表的数量,从而控制WebGL上下文的使用。示例代码如下:

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import plotly.subplots as sp
import plotly.graph_objects as go

# 创建数据帧(同之前的代码)
start_date = datetime(2018, 1, 1)
end_date = datetime(2022, 12, 31)
num_days = (end_date - start_date).days + 1
num_cols = 100
data = np.random.rand(num_days, num_cols)
dates = [start_date + timedelta(days=i) for i in range(num_days)]
df = pd.DataFrame(data, columns=[f"Column_{i+1}" for i in range(num_cols)])
df['Date'] = dates

# 创建5行2列的子图(对应10个图表分组)
fig = sp.make_subplots(rows=5, cols=2, subplot_titles=[f"Group {i+1}" for i in range(10)])

row, col = 1, 1
x = 10
while x < len(df.columns):
    columns_to_plot = df.columns[x-10:x].tolist()
    for col_name in columns_to_plot:
        fig.add_trace(go.Scatter(x=df['Date'], y=df[col_name], name=col_name), row=row, col=col)
    # 切换子图位置
    col = 2 if col == 1 else 1
    if col == 1:
        row += 1
    x += 10

fig.update_layout(height=1500, width=1200, title_text="合并后的多组折线图")
fig.show()

这种方式只需要1个WebGL上下文,完全不会触发数量限制,同时保留所有交互功能。

3. 手动清理旧图表的WebGL上下文

如果你需要保留独立图表的布局,可以在渲染新图表前手动销毁旧图表的WebGL上下文。通过Plotly.purge()方法清理指定图表的DOM元素:

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import plotly.express as px
from IPython.display import display, HTML
import plotly.io as pio

# 创建数据帧(同之前的代码)
start_date = datetime(2018, 1, 1)
end_date = datetime(2022, 12, 31)
num_days = (end_date - start_date).days + 1
num_cols = 100
data = np.random.rand(num_days, num_cols)
dates = [start_date + timedelta(days=i) for i in range(num_days)]
df = pd.DataFrame(data, columns=[f"Column_{i+1}" for i in range(num_cols)])
df['Date'] = dates

# 保存所有图表的HTML字符串
chart_htmls = []
x = 10
while x < len(df.columns):
    columns_to_plot = df.columns[x-10:x].tolist()
    fig = px.line(df, x=df['Date'], y=columns_to_plot)
    chart_htmls.append(pio.to_html(fig, full_html=False))
    x += 10

# 生成带清理逻辑的HTML,每次只渲染一个图表,切换时清理前一个
html_content = """
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="chart-container"></div>
<button id="prev-btn">上一张</button>
<button id="next-btn">下一张</button>
<script>
const charts = [""" + ",".join([f"`{html}`" for html in chart_htmls]) + """];
let currentIndex = 0;

function renderChart(index) {
    // 清理当前容器中的旧图表
    Plotly.purge('chart-container');
    // 渲染新图表
    document.getElementById('chart-container').innerHTML = charts[index];
}

renderChart(currentIndex);

document.getElementById('prev-btn').addEventListener('click', () => {
    if (currentIndex > 0) {
        currentIndex--;
        renderChart(currentIndex);
    }
});

document.getElementById('next-btn').addEventListener('click', () => {
    if (currentIndex < charts.length - 1) {
        currentIndex++;
        renderChart(currentIndex);
    }
});
</script>
"""

display(HTML(html_content))

这种方式通过分页加载图表,同一时间只存在一个WebGL上下文,彻底解决数量超限问题。


内容的提问来源于stack exchange,提问作者Marvy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 12:17:27