用 Gradio 从 Google Sheets 打造实时数据仪表盘(Public/Private 两种方案)
【免费下载链接】gradioBuild and share delightful machine learning apps, all in Python. 🌟 Star to support our work!项目地址: https://gitcode.com/GitHub_Trending/gr/gradio
Google Sheets 是团队协作中常用的表格数据载体,而把其中的数据实时“搬”进 Web 应用往往需要不少胶水代码。本指南基于 Gradio 开源仓库中的官方教程文档(中文版原始文档,英文原版位于 guides/11_other-tutorials/creating-a-realtime-dashboard-from-google-sheets.md),讲解如何仅用 9 行左右的 Python 代码,借助 Gradio Blocks 与 pandas,构建一个随 Google Sheets 数据变化而自动刷新的实时仪表盘。读完本文,你将掌握:公开表格的零认证读取方法、私有表格的 Google Cloud 服务帐号授权流程,以及gr.DataFrame/gr.LinePlot组件通过every参数驱动“函数即数据源”的定时刷新机制。
先决条件:本指南基于 Gradio Blocks(Blocks 提供了比 Interface 更灵活的布局与事件控制),请确保你已熟悉 Blocks 类的用法。公开与私有两种 Google Sheet 的处理流程略有差异,下面分别展开。
方案一:从公开 Google Sheets 构建仪表盘
得益于 pandas 库,从公开 Google Sheet 构建仪表盘极为简单,无需任何认证,因为公开表格的 CSV 导出端点可直接匿名访问。
第 1 步:获取可分享链接
打开目标 Google Sheets,点击右上角的Share(共享)按钮,再点击Get shareable link(获取可分享链接),得到形如下面的链接(关键在于 URL 中的/edit#gid=段):
https://docs.google.com/spreadsheets/d/1UoKzzRzOCt-FXLLqDKLbryEKEgllGAQUEJ5qtmmQwpU/edit#gid=0第 2 步:把 URL 改造成 CSV 导出地址并读取为 DataFrame
只需将链接中的/edit#gid=替换为/export?format=csv&gid=,Google 就会直接返回该工作表的 CSV 数据,pandas 因此可以像读普通 CSV 一样读取它(代码中用你的公开表格 URL 替换URL变量):
import pandas as pd URL = "https://docs.google.com/spreadsheets/d/1UoKzzRzOCt-FXLLqDKLbryEKEgllGAQUEJ5qtmmQwpU/edit#gid=0" csv_url = URL.replace('/edit#gid=', '/export?format=csv&gid=') def get_data(): return pd.read_csv(csv_url)这里把“数据查询”封装成了一个无参函数get_data()。函数形式是 Gradio 实现实时刷新的关键——组件会以一定周期重新调用它来取最新数据。gid参数用于定位多工作表文件中的某个 Sheet,如果你的表格只有默认的一个工作表,gid=0通常就是目标。
第 3 步:用 Blocks + 定时刷新组件拼出仪表盘
由于数据查询是一个函数,可以把它直接传给gr.DataFrame组件实时显示,或传给gr.LinePlot组件实时绘图(当然,具体用折线图还是其他图表,要视数据结构而定)。刷新频率由every参数控制,下面代码以 5 秒为周期:
import gradio as gr with gr.Blocks() as demo: gr.Markdown("# 📈 Real-Time Line Plot") with gr.Row(): with gr.Column(): gr.DataFrame(get_data, every=gr.Timer(5)) with gr.Column(): gr.LinePlot(get_data, every=gr.Timer(5), x="Date", y="Sales", y_title="Sales ($ millions)", overlay_point=True, width=500, height=500) demo.queue().launch() # Run the demo with queuing enabled运行这段代码,一个每 5 秒自动从 Google Sheets 拉取最新数据并同时更新表格与折线图的仪表盘就完成了。示例中假设表头包含Date(日期)与Sales(销售额)两列,其中x指定横轴列、y指定纵轴列;overlay_point=True会在折线上叠加数据点;width/height控制绘图区像素尺寸。
方案二:从私有 Google Sheets 构建仪表盘
私有表格无法匿名读取,流程上只多了一步——认证。关键差异在于你必须验证身份,以获准访问私有 Google Sheets。整体分为“获取凭据”与“查询数据”两个阶段。
认证:在 Google Cloud 申请服务帐号凭据
请先参考 Google 官方的凭据创建指南,具体操作如下:
- 登录你的 Google Cloud 账号,进入 Google Cloud 控制台(https://console.cloud.google.com/);
- 在控制台左上角点击汉堡菜单,选择API 和服务(APIs & Services)。若尚无项目,需先创建一个;
- 点击+ 启用 API 和服务(+ Enabled APIs & services),搜索Google Sheets API,点击进入后按下Enable(启用)。若界面上直接显示 “Manage(管理)” 按钮,说明 Sheets API 已启用;
- 在 API 和服务菜单中切换到凭据(Credentials)标签页,点击创建凭据(Create credentials);
- 在创建凭据对话框中,凭据类型选择服务帐号密钥(Service account key)并命名。务必记下该服务帐号的电子邮件地址,后面共享表格时要用它;
- 选定服务帐号后,密钥类型选择JSON,点击Create(创建),浏览器将下载包含凭据的 JSON 密钥文件,大致结构如下:
{ "type": "service_account", "project_id": "your project", "private_key_id": "your private key id", "private_key": "private key", "client_email": "email", "client_id": "client id", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://accounts.google.com/o/oauth2/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/email_id" }其中client_email就是你在第 5 步记下的服务帐号邮箱,private_key是后续签名请求所用。请妥善保管该文件,切勿提交到公开仓库或分享给他人。
查询:安装 gspread 并授权读取
拿到凭据 JSON 后,按以下步骤查询你的 Google Sheet:
- 在 Google Sheet 右上角点击Share(共享),把认证阶段第 5 步得到的服务帐号邮箱作为协作者加入(这一步非常关键,否则程序即使持有凭据也没有读取权限),再点击获取可分享链接,得到一个类似
/edit#gid=0结尾的 URL; - 安装 gspread 库——它封装了 Google Sheets API,让 Python 侧的读写更简单。在终端执行:
pip install gspread - 编写加载函数(用你的私有表格 URL 替换
URL变量):
import gspread import pandas as pd # Authenticate with Google and get the sheet URL = 'https://docs.google.com/spreadsheets/d/1_91Vps76SKOdDQ8cFxZQdgjTJiz23375sAT7vPvaj4k/edit#gid=0' gc = gspread.service_account("path/to/key.json") sh = gc.open_by_url(URL) worksheet = sh.sheet1 def get_data(): values = worksheet.get_all_values() df = pd.DataFrame(values[1:], columns=values[0]) return dfgspread.service_account()用本地 JSON 凭据完成认证;open_by_url()打开指定表格;sheet1选取默认工作表。get_data()中worksheet.get_all_values()返回二维列表,values[0]是表头、values[1:]是数据行,据此构造出带列名的 DataFrame。
- 与公开方案一致,把
get_data作为“函数式数据源”传入组件,用every参数决定刷新周期。下面是完整的私有版仪表盘代码:
import gradio as gr with gr.Blocks() as demo: gr.Markdown("# 📈 实时折线图") with gr.Row(): with gr.Column(): gr.DataFrame(get_data, every=gr.Timer(5)) with gr.Column(): gr.LinePlot(get_data, every=gr.Timer(5), x="日期", y="销售额", y_title="销售额(百万美元)", overlay_point=True, width=500, height=500) demo.queue().launch() # 启动带有排队功能的演示此时你就拥有了一个每 5 秒刷新一次、从私有 Google Sheets 拉取数据的实时仪表盘。列名(如示例中的“日期”“销售额”)要与表格表头严格一致,且建议避免中文等非 ASCII 列名带来的潜在编码问题,可将表头改为英文并在y_title/标题中展示中文文案。
背后的机制:every与gr.Timer如何驱动实时刷新
Gradio 把“定时刷新”做成了语言层面的内建能力,而非要求用户手写轮询。以本教程仓库源码为证:
gr.Timer是一个不可见的特殊组件,仅在激活时按固定间隔“跳动”。它在 gradio/components/timer.py 中实现:value参数表示两次 tick 之间的间隔(秒),默认 1 秒;active=True控制定时器是否处于激活状态;它对外暴露tick(以及change)事件。- 所有组件在构造函数中都接受
every与inputs参数。看 gradio/components/base.py 中attach_load_event()的实现:当value是函数时,组件会把它注册为“加载事件”;若every是int或float,会自动被包装为Timer(every);若显式传入Timer实例,则直接复用。随后该Timer的tick事件与组件的 value 绑定,于是每到时间点,前端就会重新请求一次后端并刷新展示。
因此本教程中gr.DataFrame(get_data, every=gr.Timer(5))与gr.LinePlot(get_data, every=gr.Timer(5), ...)的语义是:每隔 5 秒重新调用get_data(),把最新 DataFrame 重新渲染。
关于every的类型,从 gradio/components/native_plot.py 的 docstring 可确认其两种写法等价:
every: Continuously callsvalueto recalculate it ifvalueis a function (has no effect otherwise). Can provide aTimerwhose tick resetsvalue, or afloatthat provides the regular interval for the reset Timer.
即every=gr.Timer(5)与直接写every=5效果一致(float 会被内部包成Timer)。若value不是函数而是静态数据,every不会产生任何效果。
进阶:把定时器“握在手里”
gr.Timer组件不仅可以写死在组件构造参数里,还可以单独创建并通过事件动态控制。仓库中的 demo/timer_simple/run.py 展示了典型用法:
import gradio as gr import random import time with gr.Blocks() as demo: timer = gr.Timer(1) timestamp = gr.Number(label="Time") timer.tick(lambda: round(time.time()), outputs=timestamp, api_name="timestamp") number = gr.Number(lambda: random.randint(1, 10), every=timer, label="Random Number") with gr.Row(): gr.Button("Start").click(lambda: gr.Timer(active=True), None, timer) gr.Button("Stop").click(lambda: gr.Timer(active=False), None, timer) gr.Button("Go Fast").click(lambda: 0.2, None, timer)这段示例演示了三件事,可直接迁移到 Google Sheets 仪表盘中:
timer.tick(fn, outputs=...):把任意函数挂到某个定时器的 tick 事件上,实现周期性执行;- 把一个
Timer实例通过every=timer共享给多个组件,实现整页刷新节拍统一; - 运行时动态改参数:点击 “Start/Stop” 通过
gr.Timer(active=True/False)更新定时器的激活状态,点击 “Go Fast” 则把间隔动态改为 0.2 秒。
例如你可以先创建timer = gr.Timer(30)(默认 30 秒刷新一次),用 Start/Stop 按钮控制仪表盘“暂停/恢复”,让实时数据拉取完全受你掌控。
小结
仅需几行代码,就可以用gradio搭配 pandas / gspread 从公开或私有的 Google Sheets 读取数据,并在实时仪表盘中完成展示与绘图。整个过程可归纳为三步:
- 封装数据源:写一个返回 DataFrame 的
get_data()函数(公开表用pd.read_csv(csv_url),私有表用gspread+get_all_values()); - 接入组件:把该函数作为
value传给gr.DataFrame与gr.LinePlot,并指定x、y等绘图列; - 设定刷新节拍:用
every=gr.Timer(n)(或every=n)控制重新拉取数据的间隔,最后demo.queue().launch()启动服务。
由于数据源就是普通 Python 函数,这套“函数式数据 + 定时刷新”的范式同样适用于数据库、REST API、本地文件等其他任何周期性数据源;要换成柱状图、散点图等可视化形态,也只需替换为对应的原生绘图组件。若你想验证或运行一个本地可复现的定时刷新示例,直接运行 demo/timer_simple/run.py 即可观察every/Timer的实时效果。
【免费下载链接】gradioBuild and share delightful machine learning apps, all in Python. 🌟 Star to support our work!项目地址: https://gitcode.com/GitHub_Trending/gr/gradio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考