首页
/ 从 Supabase 数据创建 Gradio 实时仪表盘:完整端到端实战指南

从 Supabase 数据创建 Gradio 实时仪表盘:完整端到端实战指南

2026-09-08 17:52:07作者:滕妙奇

Supabase 是一种基于云端 PostgreSQL 的开源后端服务,提供数据库、身份认证等特性,常用于 Web 与移动应用开发。本指南演示如何把 Supabase 中存储的表格数据接入 Gradio,用原生的 gr.BarPlot 组件在浏览器中构建一个每秒/每分钟自动刷新的实时仪表盘。读完本文,你将掌握创建 Supabase 数据表、使用官方 Python 客户端写入数据、读取数据转成 pandas DataFrame,以及借助 gr.Timerevery 参数驱动图表定时刷新的完整链路,从而把任意数据库查询结果变成可分享的实时可视化应用。

Tags: TABULAR(表格数据)、DASHBOARD(仪表盘)、PLOTS(绘图)

前置条件: 需要一个免费的 Supabase 账号(前往 https://app.supabase.com/ 注册即可),并能在本机运行 Python 与 Gradio 环境。

在下面这个端到端指南中,你将学会:

  • 在 Supabase 中创建数据表
  • 使用 Supabase Python 客户端向表中写入数据
  • 使用 Gradio 将数据在实时仪表盘中可视化

如果你的数据已经在 Supabase 中、只想直接做可视化,可以跳过前两个小节,直接跳到可视化部分

在 Supabase 中创建数据表

首先我们需要一些可以可视化的数据。参考 Supabase 官方推荐的"使用 Python 加载数据"流程,我们创建一份模拟电商数据并写入 Supabase。

  1. 登录后点击 New Project 按钮,新建一个项目;
  2. 为项目命名并设置数据库密码,根据需要选择定价计划(本教程使用 Free Tier 免费版即可);
  3. 在数据库初始化期间(最长约 2 分钟),页面会展示你的 API keys,请妥善保存;
  4. 点击左侧边栏的 Table Editor(表格图标)创建新表。我们创建一张名为 Product 的单表,schema(列结构)如下:
列名 类型
product_id int8
inventory_count int8
price float8
product_name varchar
  1. 点击 Save 保存表结构。至此数据表准备完成。

说明:int8 即 64 位整数,float8 即双精度浮点数,varchar 为可变长度字符串——这三类列将来在 pandas 中分别对应整数、浮点与字符串类型,可直接被 Gradio 原生绘图组件识别与展示。

写入数据到 Supabase

接下来,我们用 Supabase 官方 Python 库把数据写入上一步创建的表中。

  1. 在终端安装 supabase 客户端:
pip install supabase
  1. 获取项目 URL 与 API Key:点击左侧边栏的 Settings(齿轮图标),再点击 API。其中 URL 显示在 Project URL 一栏;API Key 显示在 Project API keys 中(本教程使用带有 service_rolesecret 标记的密钥)。

  2. 运行以下 Python 脚本向表内写入模拟数据(需将脚本中的 SUPABASE_URLSUPABASE_SECRET_KEY 替换成第 7 步获取到的真实值):

import supabase

# 初始化 Supabase 客户端
client = supabase.create_client('SUPABASE_URL', 'SUPABASE_SECRET_KEY')

# 定义要写入的数据
import random

main_list = []
for i in range(10):
    value = {'product_id': i,
             'product_name': f"Item {i}",
             'inventory_count': random.randint(1, 100),
             'price': random.random()*100
            }
    main_list.append(value)

# 把数据写入表
data = client.table('Product').insert(main_list).execute()

代码逻辑非常直观:先生成 10 条"商品"记录(product_id 从 0 递增、inventory_count 为 1–100 的随机库存、price 为 0–100 的随机价格),随后通过 client.table('Product').insert(main_list).execute() 一次批量插入。

回到 Supabase 仪表盘并刷新页面,你应该能看到 Product 表里已经填充了 10 行数据。

安全提醒: service_role 密钥绕过行级安全(RLS),拥有对表的最高操作权限。生产环境务必通过环境变量注入、放在服务端,切勿暴露在公开的客户端代码或分享链接中。如需真实项目演示,建议仅用 anon 公钥并配合 RLS 策略限制访问范围。

可视化数据:Gradio 实时仪表盘

最后,我们仍使用同一个 supabase Python 库从数据集中读取数据,并用 gradio 构建一个实时仪表盘。

提示:本小节会重复上文的某些步骤(如创建 Supabase 客户端),以便你直接跳读。同第 7 步所述,你需要准备数据库对应的 Project URL 与 API Key。

  1. 编写一个函数,从 Product 表中加载数据并返回 pandas DataFrame:
import supabase
import pandas as pd

client = supabase.create_client('SUPABASE_URL', 'SUPABASE_SECRET_KEY')

def read_data():
    response = client.table('Product').select("*").execute()
    df = pd.DataFrame(response.data)
    return df

其中 client.table('Product').select("*").execute() 查询整张 Product 表,response.data 是由字典组成的列表,直接交给 pd.DataFrame() 即可得到结构化表格。

  1. 创建一个由 2 个柱状图组成的 Gradio 小仪表盘,每分钟绘制一次所有商品的价格与库存,并实时更新:
import gradio as gr

with gr.Blocks() as dashboard:
    with gr.Row():
        gr.BarPlot(read_data, x="product_id", y="price", title="Prices", every=gr.Timer(60))
        gr.BarPlot(read_data, x="product_id", y="inventory_count", title="Inventory", every=gr.Timer(60))

dashboard.queue().launch()

注意这里的关键技巧:gr.BarPlot() 传入一个函数而非 DataFrame。这样 Web 应用一加载,柱状图就会立刻查询数据库渲染首帧;随后由于 every 参数指定的刷新节奏,每隔 60 秒会自动重新调用 read_data 并更新图表。运行后,你的最终仪表盘应同时展示两张并排的柱状图——左侧 Prices(横轴 product_id,纵轴 price),右侧 Inventory(横轴 product_id,纵轴 inventory_count)。

源码视角:everygr.Timer 与刷新机制

这一步之所以"实时",核心在组件基类对 every 的处理。从源码看,Gradio 的原生绘图组件定义于 gradio/components/native_plot.pyBarPlot 继承自 NativePlot,其 get_mark() 方法返回 "bar"(同文件中 LinePlot 返回 "line"ScatterPlot 返回 "point"),并用它标注图表类型。

NativePlot 构造函数中与实时刷新直接相关的是两个参数(见 native_plot.py):

  • every: Timer | float | None:若 value 是函数,则每隔 every 指定的时间重新调用一次 value 来重算图表数据;
  • inputs:当 value 为函数时可传入的输入组件,输入变化时同样触发重算。

every 的底层实现链

关键机制位于组件基类 gradio/components/base.pyattach_load_event()

  • 传入 value 的可调用对象会被识别为 load_fn(见 base.pyget_load_fn_and_initial_value);
  • every 传入的是 int/float,会先被包装成 Timer 对象(every = Timer(every));
  • 随后注册 (timer, "tick") 事件,即"定时器每个 tick 触发一次重算";
  • 组件加载时先执行一次该函数作为首帧数据,之后由 Timer 的 tick 事件持续驱动刷新。

gr.Timer 本身定义于 gradio/components/timer.py,构造函数为 Timer(value: float = 1, *, active: bool = True, render: bool = True),其中 value 表示每次 tick 的间隔秒数active 表示定时器是否激活,render=False 可用于先挂载事件监听、延后渲染的场景。在 timer.py 中可见 Timer 支持 changetick 两类事件。这也是整个"每分钟刷新一次"实时行为的直接来源。

从上述调用链可以推断:本教程写法等价于给每个柱状图注册一个 60 秒周期的 Timer,每到周期触发 read_data → 查询 Supabase → 返回 DataFrame → 前端按 PlotDatamark="bar")重绘。数据写入方只要持续向表中插行,仪表盘就能在一分钟内自动呈现最新状态。

为什么需要 queue()

示例末尾使用了 dashboard.queue().launch()。定时器触发的周期性回调与多组件加载事件属于后台任务/排队请求场景,开启队列(queue)才能保证这些更新事件被后台线程可靠地调度与推送,是构建"数据自动刷新型"应用的推荐做法。

gr.BarPlot 常用参数速查

以本仓库 gradio/components/native_plot.py 的构造签名为准,除 every 外,gr.BarPlot 常用参数包括:

参数 类型 作用
value pandas DataFrame / 可调用对象 要展示的数据;传函数即实现"每次(定时/输入变化时)重查"
x str x 轴列名,可为数值、日期时间或字符串/类别
y str y 轴列名,必须为数值列
color str 用于按类别着色的列(系列)
title str 图表顶部标题(本教程即 "Prices"/"Inventory")
x_title / y_title str 自定义坐标轴标题,默认取 x/y 列名
y_aggregate "sum"/"mean"/"median"/"min"/"max"/"count" x_bin 被设置或 x 为类别时的聚合函数
x_bin number / "1h" 等 数值分箱或按 "s"/"m"/"h"/"d" 的时间分箱
sort "x"/"y"/"-x"/"-y" 或字符串列表 类别型 x 的排序方式
tooltip "axis"/"none"/"all" 或列名列表 悬停提示内容
height int 图表高度(像素)
buttons "fullscreen"/"export" 或 gr.Button() 工具栏按钮:全屏查看或导出当前视图为 PNG
every gr.Timer / float value 为函数时的定时重算间隔(秒)
inputs 组件或组件列表 value 为函数时触发重算的输入组件

其中的"实时数据源 + 自动刷新"模式同样适用于 native_plot.py 中定义的 gr.LinePlot(折线图)与 gr.ScatterPlot(散点图)——三者共享同一套 NativePlot 实现,仅 mark 不同。

扩展:构建更丰富的实时仪表盘

本教程是可继续生长的起点,几点实用的扩展方向:

  • 换数据、加图表:改用你的真实业务表,把 read_data 中的表名与 select 字段替换即可;同一行内可并排放置更多 gr.BarPlot/gr.LinePlot/gr.ScatterPlot,或配合 gr.Row()gr.Column() 布局成多图面板。
  • 联动筛选:给 gr.BarPlot 增加 inputs=gr.Dropdown(...) 之类参数,当用户切换筛选条件时即重新查询,配合 every 实现"筛选维度 + 定时刷新"两种刷新并存。
  • every 传浮点数:按 base.py 的实现,every=60 会自动被包装成 Timer(60),因此上面代码也可简写为 gr.BarPlot(read_data, x="product_id", y="price", title="Prices", every=60);把间隔调小(如 Timer(5))即可让刷新更加频繁。
  • 打印/事件交互:设置 buttons=["fullscreen", "export"] 让访问者一键全屏或导出 PNG。

如果想了解同一类组件更多用法,可继续阅读仓库内的 01_creating-plots.md(绘图基础)、02_time-plots.md(时间序列绘图)以及 04_connecting-to-a-database.md(SQLAlchemy 连接 SQLite/PostgreSQL/MySQL 的等价示例)。定时任务类应用的另一参考是 running-background-tasks.md

结语

至此,你已经学会:向 Supabase 数据集写入数据,再把数据读取出来以柱状图呈现,并让仪表盘在一分钟内自动同步最新结果。更新 Supabase 中的数据后,Gradio 仪表盘会自动随之更新——尝试在示例中加入更多图表与可视化(或换用另一份数据集),把它扩展成功能更完整的实时监控面板吧。

回顾要点:① Supabase 建表并记录 Project URL 与 service_role 密钥;② supabase.create_client 建立连接后,用 insert/select 读写数据;③ 关键一行是把 DataFrame 生成函数直接传给 gr.BarPlot(...) 并设置 every=gr.Timer(60);④ 最后用 dashboard.queue().launch() 启动服务,让定时刷新事件可靠运行。这套"数据库查询函数 + Timer 自动重算"的模式,是 Gradio 中构建各类准实时数据可视化应用的通用范式。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395