Gradio 非侵入式修改的离线使用方案

网上很多方案都是直接更换采用gradio-offline的包。但这个包很久不更新了并且是直接修改源码,所以自己打包也比较麻烦。因此这里提供了一种非侵入式的方法,动态替换部分资源的使用并重定向到本地静态资源,根据需要自己下载资源到本地就可以了。

本方案在gradio 5.34.0上测试通过。理论上兼容一个大版本应该没问题,如果有其他需求可以自己改一下。

使用方法

  1. gr_offline.py 放到你的项目中
  2. 导入补丁并在使用gradio之前调用 patch 函数
  3. 下载离线的静态资源到 ./static

使用样例

python 复制代码
import gr_offline
import gradio as gr

# 必须在使用gradio前调用一次
gr_offline.patch()

# 这个自己根据需要修改
gr.set_static_paths("./static")

def greet(name, intensity):
    return "Hello, " + name + "!" * int(intensity)

demo = gr.Interface(
    fn=greet,
    inputs=["text", "slider"],
    outputs=["text"],
)

demo.launch()

资源替换

  • CDN

    旧: https://cdnjs.cloudflare.com/{}

    新: ./static/{}

  • Google Font

    旧: https://fonts.googleapis.com/css2?family={file_name}:wght@{weight}&display=swap

    新: ./static/fonts/{file_name}/{file_name}-{weight}.woff2

原始资源下载链接

  • https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js
  • https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap

gr_offline.py

python 复制代码
def _patch_env() -> None:
    import os

    os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"


def _patch_font() -> None:
    from gradio.themes.utils.fonts import GoogleFont, LocalFont

    GoogleFont.__init__ = LocalFont.__init__  # type: ignore
    GoogleFont.stylesheet = LocalFont.stylesheet  # type: ignore


def _patch_templates() -> None:
    import re
    import types
    import jinja2
    from gradio import routes
    from fastapi.templating import Jinja2Templates

    remove_regex: list[re.Pattern] = [
        re.compile(
            r'<meta\b[^>]*?property=["']og:[^"'>]*["'][^>]*?>',
            flags=re.IGNORECASE | re.DOTALL,
        ),
        re.compile(
            r'<meta\b[^>]*?name=["']twitter:[^"'>]*["'][^>]*?>',
            flags=re.IGNORECASE | re.DOTALL,
        ),
        re.compile(
            r'<link\b[^>]*?href=["']?[^"'>]*fonts.googleapis.com[^"'>]*["']?[^>]*?>',
            flags=re.IGNORECASE | re.DOTALL,
        ),
        re.compile(
            r'<link\b[^>]*?href=["']?[^"'>]*fonts.gstatic.com[^"'>]*["']?[^>]*?>',
            flags=re.IGNORECASE | re.DOTALL,
        ),
    ]
    cdn_regex: list[re.Pattern] = [re.compile(r"https?://cdnjs.cloudflare.com/.*?")]

    def _do_patch(html: str) -> str:
        for pattern in remove_regex:
            html = re.sub(pattern, "", html)
        for pattern in cdn_regex:
            html = re.sub(pattern, "static/", html)
        return html

    def _patched_render(self: jinja2.Template, *args, **kwargs) -> str:
        html = jinja2.Template.render(self, *args, **kwargs)
        return _do_patch(html)

    async def _patched_render_async(self: jinja2.Template, *args, **kwargs) -> str:
        html = await jinja2.Template.render_async(self, *args, **kwargs)
        return _do_patch(html)

    class PatchedJinja2Templates(Jinja2Templates):
        def get_template(self, name: str) -> jinja2.Template:
            template: jinja2.Template = super().get_template(name)
            template.render = types.MethodType(_patched_render, template)
            template.render_async = types.MethodType(_patched_render_async, template)
            return template

    routes.templates = PatchedJinja2Templates(directory=routes.STATIC_TEMPLATE_LIB)
    routes.templates.env.filters["toorjson"] = routes.toorjson


def patch() -> None:
    _patch_env()
    _patch_font()
    _patch_templates()

Github:Gist

相关推荐
冷雨夜中漫步5 小时前
Python快速入门(6)——for/if/while语句
开发语言·经验分享·笔记·python
郝学胜-神的一滴6 小时前
深入解析Python字典的继承关系:从abc模块看设计之美
网络·数据结构·python·程序人生
百锦再6 小时前
Reactive编程入门:Project Reactor 深度指南
前端·javascript·python·react.js·django·前端框架·reactjs
喵手7 小时前
Python爬虫实战:旅游数据采集实战 - 携程&去哪儿酒店机票价格监控完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·采集结果csv导出·旅游数据采集·携程/去哪儿酒店机票价格监控
2501_944934737 小时前
高职大数据技术专业,CDA和Python认证优先考哪个?
大数据·开发语言·python
helloworldandy7 小时前
使用Pandas进行数据分析:从数据清洗到可视化
jvm·数据库·python
肖永威9 小时前
macOS环境安装/卸载python实践笔记
笔记·python·macos
TechWJ9 小时前
PyPTO编程范式深度解读:让NPU开发像写Python一样简单
开发语言·python·cann·pypto
枷锁—sha9 小时前
【SRC】SQL注入WAF 绕过应对策略(二)
网络·数据库·python·sql·安全·网络安全
abluckyboy10 小时前
Java 实现求 n 的 n^n 次方的最后一位数字
java·python·算法