入门 Eva J Patel(freeCodeCamp) 2026-09-10 16:14:02 · 0 阅读

第5章 Gradio 输入与输出

理解了 Gradio 的基本概念之后,接下来深入看看任何 Gradio 应用中最关键的部分之一:输入输出

一个 Gradio 应用只有能接收用户信息并返回有用的结果,才算真正有用。

听起来很简单,但用户可能提供的信息类型五花八门。

他们可能输入一句话、上传图片、从下拉菜单中选择选项、拖动滑块、上传 PDF、录制音频,或者一次性提供多种信息。

针对所有这些场景,Gradio 都有对应的组件。

什么是输入?

输入是你的应用从用户那里接收到的信息。

比如:

name = gr.Textbox()

用户可以在文本框里输入内容。

这个值随后可以传给一个 Python 函数。

看这个例子:

def greet(name):
    return f"Hello, {name}!"

这里的 name 就是输入。

什么是输出?

输出是你的应用返回给用户的信息。

比如:

output = gr.Textbox()

你的 Python 函数可能返回一个字符串,Gradio 会把它显示到这个组件里。

这种基本关系用代码表示如下:

def greet(name):
    return f"Hello, {name}!"

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    output = gr.Textbox(label="Greeting")

    button = gr.Button("Greet")

    button.click(
        fn=greet,
        inputs=name,
        outputs=output
    )

demo.launch()

第一个文本框提供输入,函数处理之后,第二个文本框展示输出。

输入和输出未必是不同的组件类型

一个常见的误解是:某些组件是“输入组件”,另一些是“输出组件”。

实际上,很多 Gradio 组件两种角色都能胜任。

例如:

gr.Textbox()

既可以接收文本,也可以显示文本。

同样地:

gr.Image()

用于接收或显示图像。

组件的用法取决于它连接在哪里。

一个输入与一个输出

从最简单的模式开始。

import gradio as gr

def double(number):
    return number * 2

with gr.Blocks() as demo:
    number = gr.Number(label="Number")
    result = gr.Number(label="Result")

    button = gr.Button("Double")

    button.click(
        fn=double,
        inputs=number,
        outputs=result
    )

demo.launch()

用户输入一个数字,点击按钮触发 double(),随后显示结果。

多个输入

Python 函数可以接收多个参数。

例如:

def calculate_total(price, quantity):
    return price * quantity

该函数需要两个输入。

我们提供两个组件:

import gradio as gr

def calculate_total(price, quantity):
    return price * quantity

with gr.Blocks() as demo:
    price = gr.Number(label="Price")
    quantity = gr.Number(label="Quantity")

    result = gr.Number(label="Total")

    button = gr.Button("Calculate")

    button.click(
        fn=calculate_total,
        inputs=[price, quantity],
        outputs=result
    )

demo.launch()

这个列表:

inputs=[price, quantity]

决定了值传入函数的顺序。

第一个组件提供 price

第二个提供 quantity

从概念上讲,Gradio 执行的是:

calculate_total(price_value, quantity_value)

多个输出

函数也可以返回多个值。

假设我们想分析一句话:

def analyze_text(text):
    characters = len(text)
    words = len(text.split())

    return characters, words

函数返回两个值,因此我们提供两个输出:

import gradio as gr

def analyze_text(text):
    characters = len(text)
    words = len(text.split())

    return characters, words

with gr.Blocks() as demo:
    text = gr.Textbox(
        label="Text",
        lines=6
    )

    characters = gr.Number(
        label="Characters"
    )

    words = gr.Number(
        label="Words"
    )

    button = gr.Button("Analyze")

    button.click(
        fn=analyze_text,
        inputs=text,
        outputs=[characters, words]
    )

demo.launch()

第一个返回值传给第一个输出组件,第二个返回值传给第二个输出组件。

输出顺序很重要

假设:

def analyze_text(text):
    return characters, words

和:

outputs=[characters_output, words_output]

顺序一一对应,没有问题。

但如果不小心写成:

outputs=[words_output, characters_output]

数值就会显示到错误的位置。

所以保持输入和输出顺序清晰非常重要。

用字典表示结构化结果

有时应用会生成多条相关信息。

在 Python 中可以返回一个字典:

def analyze_person(name, age):
    return {
        "name": name,
        "age": age,
        "adult": age >= 18
    }

然后用合适的组件(如 gr.JSON)来展示结果。

import gradio as gr

def analyze_person(name, age):
    return {
        "name": name,
        "age": age,
        "adult": age >= 18
    }

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    age = gr.Number(label="Age")

    output = gr.JSON(label="Result")

    button = gr.Button("Analyze")

    button.click(
        fn=analyze_person,
        inputs=[name, age],
        outputs=output
    )

demo.launch()

当函数产出结构化信息时,这种方式非常实用。

输入组件可以设置默认值

可以为组件提供初始值。

例如:

gr.Textbox(
    value="Hello!"
)

或者:

gr.Number(
    value=10
)

又或者:

gr.Slider(
    minimum=0,
    maximum=100,
    value=50
)

这样能让应用更容易理解,因为用户一眼就能看出组件期望什么样的值。

标签帮助用户理解界面

对比一下:

gr.Textbox()

和:

gr.Textbox(
    label="Enter your question"
)

第二种写法传达的信息要清晰得多。

标签应该描述组件的用途,而不是简单地重复它的数据类型。

例如,这样写:

gr.Textbox(label="Question")

通常比这样更有用:

gr.Textbox(label="Textbox")

占位文本

占位符可以在不真正填入内容的情况下给出示例。

gr.Textbox(
    label="Question",
    placeholder="Ask something about your document..."
)

用户一开始输入,占位符就会消失。因此它很适合用来展示示例和提示。

valueplaceholder 的区别

看这个例子:

gr.Textbox(
    value="Hello"
)

此时文本框里真的包含 "Hello"

再看看这个:

gr.Textbox(
    placeholder="Type something here..."
)

文本框是空的,那句话只是作为提示显示出来。

设计表单时,这个区别很重要。

行数与更大的文本区域

如果需要输入较长的文本,可以这样设置:

gr.Textbox(
    lines=10
)

这样能给用户更多的输入空间。

一个文本生成应用可能会这样写:

prompt = gr.Textbox(
    label="Prompt",
    lines=8,
    placeholder="Describe what you want the AI to generate..."
)

让组件不可交互

有时你希望用户只能查看信息,而非编辑。你可以通过 interactive 参数控制组件是否可交互。

例如:

output = gr.Textbox(
    label="Generated Result",
    interactive=False
)

这对输出类组件尤其有用。

让组件不可见

你也可以通过 visible 参数控制组件的可见性。

gr.Textbox(
    visible=False
)

当某个组件只在特定条件下才需要显示时,这一点很有用。后面会介绍如何根据事件动态修改组件属性。

组件不必直接绑定按钮

用户修改组件值时同样可以触发交互。

例如:

name.change(
    fn=greet,
    inputs=name,
    outputs=output
)

这样函数在值变化时直接运行,而无需等待按钮点击。第 7 章将深入讲解事件机制。

理解数据类型

不同组件天然对应不同类型的数据:Textbox 处理字符串,Number 处理数值,Image 处理图像数据,Checkbox 对应布尔值,Dropdown 返回选中项,Slider 返回数值。

这一点很重要,因为 Python 函数需要匹配组件提供的数据类型。例如:

def is_adult(age):
    return age >= 18

这里用 Number 更合适。如果改用 Textbox,就需要手动把字符串转成数字:

def is_adult(age):
    age = int(age)
    return age >= 18

选择合适的组件可以减少不必要的数据转换。

手动转换输入值

有时转换是绕不开的。例如:

def calculate_age_in_months(age):
    return int(age) * 12

如果你接收的是文本,可能需要先做类型转换:

age = int(age)

但别盲目转换。

用户可能输入意料之外的值。例如,下面这行会直接报错:

int("hello")

好的应用会在处理前校验输入。

输入校验

假设有如下代码:

def divide(a, b):
    return a / b

如果 b 为零会怎样?Python 会抛出异常。

更安全的写法是:

def divide(a, b):
    if b == 0:
        return "You cannot divide by zero."

    return a / b

这样应用就能返回一条有意义的提示信息,而不是让交互直接崩溃。

随着应用复杂度增加,输入校验也越来越重要。

多输入表单

我们来搭一个简单的个人简介生成器。

import gradio as gr

def create_profile(name, age, occupation):
    return (
        f"Name: {name}\n"
        f"Age: {age}\n"
        f"Occupation: {occupation}"
    )

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    age = gr.Number(label="Age")
    occupation = gr.Textbox(label="Occupation")

    button = gr.Button("Create Profile")

    output = gr.Textbox(
        label="Profile"
    )

    button.click(
        fn=create_profile,
        inputs=[name, age, occupation],
        outputs=output
    )

demo.launch()

这展示了一个你会反复使用的模式:收集 → 处理 → 展示。

输入不必来自同一类组件

你可以混合使用不同类型的组件。

例如:

def create_message(name, age, subscribed):
    status = "subscribed" if subscribed else "not subscribed"

    return f"{name} is {age} years old and is {status}."

界面上可以这样定义:

name = gr.Textbox()
age = gr.Number()
subscribed = gr.Checkbox()

然后:

button.click(
    fn=create_message,
    inputs=[name, age, subscribed],
    outputs=output
)

Gradio 会按正确的顺序传入这些值。

可选输入

你的 Python 函数也可以定义默认值。

例如:

def greet(name, greeting="Hello"):
    return f"{greeting}, {name}!"

这时需要仔细考虑可选参数与界面之间的交互方式。

在许多应用中,把选项明确暴露出来会更清晰:

greeting = gr.Dropdown(
    choices=["Hello", "Hi", "Welcome"]
)

然后:

button.click(
    fn=greet,
    inputs=[name, greeting],
    outputs=output
)

这样用户就能直接控制选项了。

把输入输出视为应用契约

可以把组件理解为一种契约。

你的函数声明:

"给我这些值,我返回这些结果。"

你的 Gradio 界面声明:

"我负责从用户那里收集这些值,并展示这些结果。"

当双方达成一致时,应用就能顺畅运行。

一旦不一致,就会遇到报错或令人困惑的行为。

动手试一试

我们来构建一个温度转换器。

你的应用应该:

  • 接受一个摄氏温度

  • 将其转换为华氏温度

  • 展示转换结果

从这个 Python 函数开始:

def celsius_to_fahrenheit(celsius):
    return (celsius * 9 / 5) + 32

然后自己动手创建 Gradio 界面。

成功运行后,再修改它,让用户可以在摄氏和华氏之间选择。

要点回顾

  • 输入是传给 Python 函数的值。

  • 输出是返回给用户的值。

  • 函数可以有多个输入。

  • 函数可以返回多个输出。

  • 输入输出的顺序很重要。

  • 组件类型应与应用所需的数据相匹配。

  • 标签和占位符能让界面更易理解。

  • 校验可防止无效的用户输入引发故障。

  • 组件根据连接方式不同,既可以作为输入,也可以作为输出。

评论 (0)