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

Flask中Plotly图表转JSON遇循环引用错误求助

Flask中Plotly图表转JSON触发循环引用错误的解决

问题详情

在Flask应用中使用Plotly展示DataFrame生成的折线图,DataFrame数据正常(见Figure 1),调用fig.show()可正常显示图表,但执行json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)转换为JSON时,触发以下错误:

Traceback (most recent call last):
  File "/Users/benjamin/PycharmProjects/sorare-app/webapp.py", line 32, in homepage
    graph_json = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
  File "/Users/benjamin/PycharmProjects/sorare-collect/venv/lib/python3.10/site-packages/dynamodb_json/json_util.py", line 40, in dumps
    result_ = TypeSerializer().serialize(json.loads(json.dumps(dct, default=json_serial),
  File "/Users/benjamin/PycharmProjects/sorare-collect/venv/lib/python3.10/site-packages/simplejson/__init__.py", line 412, in dumps
    **kw).encode(obj)
  File "/Users/benjamin/PycharmProjects/sorare-collect/venv/lib/python3.10/site-packages/simplejson/encoder.py", line 296, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/Users/benjamin/PycharmProjects/sorare-collect/venv/lib/python3.10/site-packages/simplejson/encoder.py", line 378, in iterencode
    return _iterencode(o, 0)
ValueError: Circular reference detected

完整代码

leaderboards = football_so5_leaderboards.get_leaderboards_in_group("global-all_star-division-4", dynamodb_client)
df = pd.DataFrame(json.loads(leaderboards))
print(df)
fig = px.line(df, x = 'so5_fixture_gameweek', y='last_rewarded_score', title='Average Last Rewarded Score', labels={
                 'so5_fixture_gameweek': 'Gameweek',
                 'last_rewarded_score': 'Score'
                })
fig.show()
print(fig)
graph_json = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
return render_template('homepage.html', grap_json=graph_json)

Figure 1: DataFrame数据

so5_fixture_gameweek  last_rewarded_score
0                    298               341.25
1                    299               322.81
2                    300                 0.00
3                    301               360.42
4                    302               347.76
5                    303                 0.00
6                    304               345.43
7                    305                 0.00
8                    306                 0.00
9                    307               302.05
10                   308                 0.00
11                   309               296.09
12                   310                 0.00
13                   311                 0.00
14                   312                 0.00
15                   313                 0.00
16                   314               332.46
17                   315               353.26
18                   316               332.81
19                   317               364.27
20                   318               342.25
21                   319               356.51
22                   320               333.90
23                   321               333.16

Figure 2: Plotly Figure对象输出

Figure({
    'data': [{'hovertemplate': 'Gameweek=%{x}<br>Score=%{y}<extra></extra>',
              'legendgroup': '',
              'line': {'color': '#636efa', 'dash': 'solid'},
              'marker': {'symbol': 'circle'},
              'mode': 'lines',
              'name': '',
              'orientation': 'v',
              'showlegend': False,
              'type': 'scatter',
              'x': array([298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311,
                          312, 313, 314, 315, 316, 317, 318, 319, 320, 321]),
              'xaxis': 'x',
              'y': array([341.25, 322.81,   0.  , 360.42, 347.76,   0.  , 345.43,   0.  ,   0.  ,
                          302.05,   0.  , 296.09,   0.  ,   0.  ,   0.  ,   0.  , 332.46, 353.26,
                          332.81, 364.27, 342.25, 356.51, 333.9 , 333.16]),
              'yaxis': 'y'}],
    'layout': {'legend': {'tracegroupgap': 0},
               'template': '...',
               'title': {'text': 'Average Last Rewarded Score'},
               'xaxis': {'anchor': 'y', 'domain': [0.0, 1.0], 'title': {'text': 'Gameweek'}},
               'yaxis': {'anchor': 'x', 'domain': [0.0, 1.0], 'title': {'text': 'Score'}}}
})

解决方法

1. 使用Plotly内置的to_json()方法

Plotly的Figure对象自带序列化方法,无需手动调用json.dumps,该方法已内置处理循环引用的逻辑,直接替换代码中JSON转换的行:

graph_json = fig.to_json()

2. 排查json模块冲突

从错误栈可见,实际调用的是dynamodb_json.json_util中的dumps方法,而非Python标准库的json模块。如果代码中存在from dynamodb_json import json_util as json这类导入语句,会覆盖标准json模块,导致序列化逻辑冲突。

  • 若要继续使用标准库json,需确保导入的是标准模块:
    import json
    graph_json = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
    
  • 更推荐使用Plotly自带的to_json(),避免模块冲突问题。

3. 验证模板变量拼写

代码中传递给模板的变量是grap_json,需确保前端模板中使用的变量名完全一致,避免拼写错误导致图表无法渲染。示例前端渲染代码:

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="chart"></div>
<script>
    var graph = {{ grap_json|safe }};
    Plotly.newPlot('chart', graph.data, graph.layout);
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 18:05:46