
在 Gradio 应用中运行后台任务构建自动备份到 HuggingFace Dataset 的反馈收集应用【免费下载链接】gradioBuild and share delightful machine learning apps, all in Python. Star to support our work!项目地址: https://gitcode.com/GitHub_Trending/gr/gradio本篇技术指南讲解如何让 Gradio 应用脱离“请求—响应”生命周期在后台执行一次性或周期性的任务如定时同步数据库、邮件发送预测报告。我们将基于本仓库官方教程 running-background-tasks.md 的主体思路从零构建一个“Google 表单”风格的 Gradio 反馈收集应用用户提交的评审写入本地 SQLite 数据库应用内通过后台任务每 60 秒把数据库自动备份到 HuggingFace Dataset。读完本文你将掌握三种能力用sqlite3编写独立于 Web 层的数据访问逻辑、用gr.Blocks布局表单与统计面板、用任务调度器在 Gradio 进程内无侵入地注册定时后台任务。先厘清概念什么是“后台任务”Gradio 的事件监听如按钮点击、demo.load页面加载默认都运行在请求—响应生命周期内前端触发事件 → 后端执行绑定函数 → 返回结果渲染到组件。而后台任务指的是你希望在这个生命周期之外执行的操作——无论执行一次还是周期性循环它们都不需要用户请求来驱动。典型场景包括周期性把本地数据库同步到外部存储做灾备定时汇总模型预测结果并发送报告定期清理临时文件、拉取最新模型权重等运维操作。本教程选取了一个最具代表性的组合本地 SQLite 做即时读写 HuggingFace Dataset 做异地备份 调度器驱动同步。关键点在于Gradio 本身不提供调度原语后台任务完全由常规 Python 调度库承担Gradio 只负责提供一个持续运行的进程因此你可以自由选择任何你熟悉的任务调度方案。总体设计一份“Google 表单”风格的评审应用我们要构建的应用收集用户对 Gradio 库的反馈。一次提交包含三个字段评审人姓名文本、满意度评分15 的单项选择、附加评论多行文本。提交后立即写入本地reviews.db右侧面板实时刷新最近 10 条评审记录和评审总数。示意图大致如下左列输入gr.Textbox姓名、gr.Radio评分 1–5、gr.Textbox评论多行、gr.Button提交右列输出gr.Dataframe最近 10 条记录、gr.Number总评审数后台APScheduler 的BackgroundScheduler每 60 秒把reviews.db复制进本地 Dataset 仓库目录并推送push到 HuggingFace Hub。下面的步骤与官方指南一一对应每一步代码都可以独立运行、组合成一个完整应用。Step 1编写数据库逻辑教程使用 Python 标准库sqlite3连接数据库——Gradio 对存储层没有任何限制MySQL、PostgreSQL、MongoDB 均可这里选择 SQLite 只是因为零配置、最适合演示。首先是初始化数据库表。reviews表包含自增主键id、自动写入的created_at时间戳、以及name、review、comments三个业务字段DB_FILE ./reviews.db db sqlite3.connect(DB_FILE) # Create table if it doesnt already exist try: db.execute(SELECT * FROM reviews).fetchall() db.close() except sqlite3.OperationalError: db.execute( CREATE TABLE reviews (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, name TEXT, review INTEGER, comments TEXT) ) db.commit() db.close()注意这里的技巧直接查询表来探测其是否存在捕获sqlite3.OperationalError表不存在时抛出再执行建表语句。在表已存在的情况下只是做了次空查询就关闭连接。接着定义两个业务函数。get_latest_reviews读取最新 10 条记录并顺带返回总记录数两个返回值都整理成pandas.DataFrame与整数后续可直接交给gr.Dataframe和gr.Number渲染def get_latest_reviews(db: sqlite3.Connection): reviews db.execute(SELECT * FROM reviews ORDER BY id DESC limit 10).fetchall() total_reviews db.execute(Select COUNT(id) from reviews).fetchone()[0] reviews pd.DataFrame(reviews, columns[id, date_created, name, review, comments]) return reviews, total_reviews def add_review(name: str, review: int, comments: str): db sqlite3.connect(DB_FILE) cursor db.cursor() cursor.execute(INSERT INTO reviews(name, review, comments) VALUES(?,?,?), [name, review, comments]) db.commit() reviews, total_reviews get_latest_reviews(db) db.close() return reviews, total_reviewsadd_review用参数化 SQL?占位符写入新评审这是防 SQL 注入的标准写法写入后立刻复用get_latest_reviews返回最新面板数据一次事件完成“写入 刷新”。由于后台任务线程与 Gradio 事件线程可能同时访问数据库本示例刻意让每个函数独立sqlite3.connect(DB_FILE)、用完即close()避免跨线程共享连接对象SQLite 自身的文件锁机制会保证并发的串行化写入。最后补一个供页面加载时调用的函数它只读并返回最新面板数据def load_data(): db sqlite3.connect(DB_FILE) reviews, total_reviews get_latest_reviews(db) db.close() return reviews, total_reviews把上述三个函数集中到一个文件例如app.py并补充import sqlite3、import pandas as pd数据库层即完成。更复杂的“读取数据库 → 展示到组件”模式可以参考本仓库指南 04_connecting-to-a-database.md。Step 2用gr.Blocks搭建动态页面有了数据层我们就能用 Gradio 的 Blocks 低层 API 精确编排布局与事件。gr.Row与gr.Column负责把页面切成左右两栏左栏放输入组件与提交按钮右栏放两块实时面板with gr.Blocks() as demo: with gr.Row(): with gr.Column(): name gr.Textbox(labelName, placeholderWhat is your name?) review gr.Radio(labelHow satisfied are you with using gradio?, choices[1, 2, 3, 4, 5]) comments gr.Textbox(labelComments, lines10, placeholderDo you have any feedback on gradio?) submit gr.Button(valueSubmit Feedback) with gr.Column(): data gr.Dataframe(labelMost recently created 10 rows) count gr.Number(labelTotal number of reviews) submit.click(add_review, [name, review, comments], [data, count]) demo.load(load_data, None, [data, count])两个事件监听决定了页面行为submit.click(add_review, inputs, outputs)按钮点击时把三个输入组件的当前值传给add_review返回值分别更新data与count两个输出组件——DataFrame渲染为表格、整数渲染到Numberdemo.load(load_data, None, outputs)页面首次加载时执行load_data用已有历史记录初始化面板。demo.load在仓库中大量出现例如 blocks_page_load/run.py 就是用页面加载事件触发函数输出的最小范例。完成这一步其实已经可以直接demo.launch()运行应用功能完整。Blocks 的事件注册与启动入口分别对应 blocks.py 中queue()L2556与launch()L2657的实现。若未来表单流量增大、希望同一时间只串行处理部分写入可在启动前调用demo.queue()让事件进入排队与并发受限的执行流程详见 01_queuing.md。Step 3用调度器把本地库定时同步到 HuggingFace DatasetStep 2 的应用有一个隐患所有评审都只存在本机 SQLite 文件里一旦文件误删数据将全部丢失。解决方案是把评审备份到云端 Dataset。3.1 准备工作创建 Dataset 与访问令牌前往 HuggingFace 平台的 Dataset 页面创建一个新的数据集仓库记录其名称。然后进入“Settings”页面生成一个访问令牌Access Token该令牌必须对目标 Dataset 拥有写入WRITE权限因为后台任务要向它推送数据。不要在脚本中硬编码令牌。推荐通过环境变量注入部署到 Spaces 时再把环境变量配置为加密的 Secret见 Step 4。令牌的官方语义是“程序化认证”读、写、管理等权限范围由令牌本身的 scope 决定。3.2 启动时拉取最新备份在脚本顶部任何写入发生之前用 HuggingFace Hub 客户端连接数据集并恢复最近一次备份。以下代码原样来自官方指南请注意其中的Repository辅助类来自huggingface_hubGradio 本体不依赖它需要单独安装import os import huggingface_hub import shutil TOKEN os.environ.get(HUB_TOKEN) repo huggingface_hub.Repository( local_dirdata, repo_typedataset, clone_fromname-of-your-dataset, use_auth_tokenTOKEN ) repo.git_pull() shutil.copyfile(./data/reviews.db, DB_FILE)这段代码把远程 Dataset 克隆到本地data/目录git_pull()拉取最新提交然后把其中的reviews.db覆盖回本地工作库——实现了“应用重启后自动恢复云端备份”。它之所以放在最顶部是为了保证恢复先于任何新写入避免本地数据盖掉云端数据。有一点需要说明Repository是huggingface_hub中偏“历史形态”的封装类其参数与行为随库版本演进新版本更推荐无状态风格的上传 API由于 Gradio 只负责提供运行进程、不绑定任何 Hub 客户端若你的huggingface_hub版本较新导致Repository参数报错请以该库当前官方文档为准同步思路不变。3.3 注册每 60 秒执行一次的备份任务本教程选用 APSchedulerAdvanced Python Scheduler完成调度但正如指南所强调的这不是唯一选择——schedule、Celery beat、乃至你自己写的while True sleep线程循环都可以。使用 APScheduler 的关键代码from apscheduler.schedulers.background import BackgroundScheduler import pandas as pd import datetime def backup_db(): shutil.copyfile(DB_FILE, ./data/reviews.db) db sqlite3.connect(DB_FILE) reviews db.execute(SELECT * FROM reviews).fetchall() pd.DataFrame(reviews).to_csv(./data/reviews.csv, indexFalse) print(updating db) repo.push_to_hub(blockingFalse, commit_messagefUpdating data at {datetime.datetime.now()}) scheduler BackgroundScheduler() scheduler.add_job(funcbackup_db, triggerinterval, seconds60) scheduler.start()逐步拆解这段代码的行为复制数据库文件shutil.copyfile(DB_FILE, ./data/reviews.db)把本地库快照进 Dataset 仓库目录导出 CSV同时把全表导出为reviews.csv便于在 Dataset 平台上直接预览表格数据推送repo.push_to_hub(blockingFalse, ...)把本地data/目录的改动提交到远程。blockingFalse很关键——它让推送在后台异步完成任务线程不必干等网络 IO 结束提交消息附带时间戳datetime.datetime.now()方便日后追溯每次备份时间点注册调度scheduler.add_job(funcbackup_db, triggerinterval, seconds60)注册一个间隔触发器任务每 60 秒执行一次BackgroundScheduler在自己的后台线程中运行不会阻塞 Gradio 主进程的事件循环启动scheduler.start()后任务即开始周期性执行。由于调度器与demo.launch()运行在同一 Python 进程中只要应用进程存活备份就会持续进行这与“每次请求才触发”的 Web 事件形成鲜明对照正是后台任务的精髓。backup_db中读取全表数据生成DataFrame是额外补充的细节它让备份不只有.db二进制快照还多一份人可直接查看的 CSV二者共同保证“即使数据库格式变化原始评审数据仍以通用格式保留”。Step 4加分项部署到 HuggingFace Spaces你可以用 HuggingFace Spaces 平台免费托管这个应用体验完整的“Gradio 后台任务”生产形态参照本仓库指南 01_using-hugging-face-integrations.md 创建 Space 并把代码推送上去在 Space 的设置页把HUB_TOKEN添加为Secret 环境变量而不是明文写进代码——对应本示例中os.environ.get(HUB_TOKEN)的读取方式在 Space 根目录提供requirements.txt显式声明gradio、apscheduler、pandas、huggingface_hub等依赖让 Space 启动时自动安装启动后 Space 进程会常驻运行APScheduler 与 Blocks 应用共享进程生命周期因此后台备份会一直执行。部署到 Spaces 还顺带解决了一个 SQLite 特有的问题Spaces 的文件系统在实例重启后是临时的本地reviews.db可能丢失。好在 Step 3.2 的“启动即从云端拉取备份”逻辑已经闭环——每次冷启动都会先恢复云端最新备份再接受新的评审写入数据永不丢失。总结与延伸阅读至此你完成了三件事用sqlite3编写与 Web 层解耦的数据访问逻辑用gr.Blocks的Row/Column布局和click、load事件监听构建表单应用用 APScheduler 的BackgroundScheduler以interval触发器让数据库每 60 秒自动备份到 HuggingFace Dataset。核心心法是——Gradio 不内置调度能力后台任务由应用进程内任何常规 Python 调度方案承担二者共享进程生命周期、互不阻塞。若想继续深入本仓库相关主题推荐阅读官方原文档running-background-tasks.md数据展示层04_connecting-to-a-database.md、styling-the-gradio-dataframe.md事件与排队01_queuing.md、blocks_page_load/run.py部署与集成01_using-hugging-face-integrations.md。尝试把这些组件替换为你自己的业务把 SQLite 换成 PostgreSQL、把备份目标换成内部对象存储、把调度频率从 60 秒改成每天凌晨执行——方法完全一致。【免费下载链接】gradioBuild and share delightful machine learning apps, all in Python. Star to support our work!项目地址: https://gitcode.com/GitHub_Trending/gr/gradio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考