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

相关推荐
BU摆烂会噶5 小时前
【LangGraph】持久化实现的三大能力——人机交互
数据库·人工智能·python·langchain·人机交互
.柒宇.6 小时前
AI掘金头条项目部署实践指南
linux·运维·python·fastapi
WL_Aurora6 小时前
Python 算法基础篇之树和二叉树
python·算法
小郑加油6 小时前
python学习Day11:认识与创建CSV文件
开发语言·python·学习
Pkmer6 小时前
Java程序员大战Python面向对象
python·ai编程
小龙报6 小时前
【Coze-AI智能体平台】低代码省时高效:Coze 应用开发全流程指南
java·人工智能·python·深度学习·低代码·chatgpt·交互
技术钱6 小时前
LCEL表达式与Runnable可运行协议
python
Echo_NGC22376 小时前
【论文解读】Attention Is All You Need —— AI 时代的“开山之作“,经典中的经典(transformer小白导读)
人工智能·python·深度学习·神经网络·机器学习·conda·transformer
jingqingdai36 小时前
别用正则格式化 HTML!我用 DOM 遍历实现零风险本地格式化,老项目重构效率直接拉满
前端·重构·html