Python library for easily interacting with trained machine learning models
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Reactive event system for connecting user interactions to Python functions with comprehensive event data, dependency management, and support for complex interaction patterns.
Structured data objects that provide information about user interactions and system events, enabling detailed event handling logic.
class EventData:
def __init__(self, target, data):
"""
Base event information with metadata.
Attributes:
- target: Component that triggered the event
- data: Event-specific data payload
"""
class SelectData(EventData):
def __init__(self, index, value, selected):
"""
Selection event data with index/value information.
Attributes:
- index: Selected item index (int or tuple for 2D selections)
- value: Selected item value
- selected: Whether item is selected (bool)
"""
class KeyUpData(EventData):
def __init__(self, key, input_value):
"""
Keyboard input event data with key information.
Attributes:
- key: Key that was pressed (string)
- input_value: Current input value after key press
"""
class LikeData(EventData):
def __init__(self, index, value, liked):
"""
Like/dislike event data for feedback systems.
Attributes:
- index: Index of liked/disliked item
- value: Value of liked/disliked item
- liked: Whether item was liked (True) or disliked (False)
"""
class RetryData(EventData):
def __init__(self, index, value):
"""
Retry action event data for error handling.
Attributes:
- index: Index of item being retried
- value: Value of item being retried
"""
class UndoData(EventData):
def __init__(self, index, value):
"""
Undo action event data for edit operations.
Attributes:
- index: Index of item being undone
- value: Previous value before undo
"""
class EditData(EventData):
def __init__(self, index, value):
"""
Edit operation event data with change information.
Attributes:
- index: Index of edited item
- value: New value after edit
"""
class DownloadData(EventData):
def __init__(self, value):
"""
Download event data with file information.
Attributes:
- value: File path or data being downloaded
"""
class CopyData(EventData):
def __init__(self, value):
"""
Copy operation event data for clipboard actions.
Attributes:
- value: Data being copied to clipboard
"""
class DeletedFileData(EventData):
def __init__(self, file):
"""
File deletion event data with file metadata.
Attributes:
- file: FileData object of deleted file
"""Functions and methods for registering event handlers and managing event dependencies between components.
def on(
triggers,
fn,
inputs=None,
outputs=None,
api_name=None,
status_tracker=None,
preprocess=True,
postprocess=True,
scroll_to_output=False,
show_progress="full",
queue=None,
batch=False,
max_batch_size=4,
concurrency_limit=None,
concurrency_id=None,
**kwargs
):
"""
Generic event listener for custom events.
Parameters:
- triggers: List of component.event_name pairs to listen to
- fn: Function to call when event occurs
- inputs: Input components to pass to function
- outputs: Output components to update with results
- api_name: Name for API endpoint (None for no API)
- status_tracker: Status indicator component
- preprocess: Whether to preprocess inputs
- postprocess: Whether to postprocess outputs
- scroll_to_output: Whether to scroll to outputs
- show_progress: Progress indicator ("full", "minimal", "hidden")
- queue: Whether to queue the event
- batch: Whether to batch process multiple inputs
- max_batch_size: Maximum batch size
- concurrency_limit: Maximum concurrent executions
- concurrency_id: Identifier for concurrency limiting
"""
class Dependency:
def __init__(
self,
trigger,
fn,
inputs,
outputs,
**kwargs
):
"""
Event dependency configuration and chaining.
Parameters:
- trigger: Component event that triggers this dependency
- fn: Function to execute
- inputs: Input components
- outputs: Output components
"""
def then(self, fn, inputs=None, outputs=None, **kwargs):
"""Chain another function to execute after this one."""
def success(self, fn, inputs=None, outputs=None, **kwargs):
"""Execute function only on successful completion."""
def error(self, fn, inputs=None, outputs=None, **kwargs):
"""Execute function only on error."""
def api(name):
"""
API endpoint decorator for HTTP exposure.
Parameters:
- name: Name for the API endpoint
Returns:
- Decorator function for marking functions as API endpoints
"""Event handling methods available on all interactive components for connecting user interactions to Python functions.
# Standard event methods available on most components
def change(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when component value changes."""
def click(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when component is clicked (buttons, clickable elements)."""
def select(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when item is selected (galleries, dataframes, lists)."""
def submit(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when form is submitted (textboxes, forms)."""
def input(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered on input changes (textboxes, sliders)."""
def focus(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when component gains focus."""
def blur(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when component loses focus."""
def upload(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when file is uploaded (file components)."""
def play(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when media starts playing (audio, video)."""
def pause(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when media is paused."""
def like(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when item is liked/disliked (chatbot)."""
def retry(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when retry is requested."""
def undo(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when undo is requested."""
def edit(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when item is edited."""
def delete(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when item is deleted."""
def copy(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when item is copied."""
def key_up(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered when key is released."""
def stream(self, fn, inputs=None, outputs=None, **kwargs):
"""Triggered for streaming data updates."""Simple event handlers connecting component interactions to functions:
import gradio as gr
def process_text(text):
return text.upper()
def button_clicked():
return "Button was clicked!"
with gr.Blocks() as demo:
input_text = gr.Textbox(label="Input")
output_text = gr.Textbox(label="Output")
submit_btn = gr.Button("Submit")
status_text = gr.Textbox(label="Status")
# Button click event
submit_btn.click(
fn=process_text,
inputs=input_text,
outputs=output_text
)
# Input change event
input_text.change(
fn=lambda x: f"Typing: {x}",
inputs=input_text,
outputs=status_text
)Using event data objects to access detailed interaction information:
import gradio as gr
def handle_selection(evt: gr.SelectData):
return f"Selected item {evt.index} with value: {evt.value}"
def handle_like(evt: gr.LikeData):
action = "liked" if evt.liked else "disliked"
return f"You {action} message {evt.index}: {evt.value}"
def handle_keypress(evt: gr.KeyUpData):
return f"Key pressed: {evt.key}, Current text: {evt.input_value}"
with gr.Blocks() as demo:
# Gallery with selection handling
gallery = gr.Gallery(["image1.jpg", "image2.jpg"])
selection_output = gr.Textbox(label="Selection")
gallery.select(
fn=handle_selection,
outputs=selection_output
)
# Chatbot with like/dislike
chatbot = gr.Chatbot(likeable=True)
like_output = gr.Textbox(label="Feedback")
chatbot.like(
fn=handle_like,
outputs=like_output
)
# Text input with key handling
text_input = gr.Textbox(label="Type here")
key_output = gr.Textbox(label="Key presses")
text_input.key_up(
fn=handle_keypress,
outputs=key_output
)Chaining multiple functions and handling success/error cases:
import gradio as gr
def process_step1(text):
if not text:
raise ValueError("Empty input")
return text.upper()
def process_step2(text):
return f"Processed: {text}"
def handle_success():
return "Processing completed successfully!"
def handle_error(error):
return f"Error occurred: {str(error)}"
with gr.Blocks() as demo:
input_text = gr.Textbox(label="Input")
output_text = gr.Textbox(label="Output")
status_text = gr.Textbox(label="Status")
submit_btn = gr.Button("Process")
# Chain multiple processing steps
submit_btn.click(
fn=process_step1,
inputs=input_text,
outputs=output_text
).then(
fn=process_step2,
inputs=output_text,
outputs=output_text
).success(
fn=handle_success,
outputs=status_text
).error(
fn=handle_error,
outputs=status_text
)Using the on function for complex event combinations:
import gradio as gr
def multi_trigger_handler(text1, text2):
return f"Combined: {text1} + {text2}"
with gr.Blocks() as demo:
text1 = gr.Textbox(label="Text 1")
text2 = gr.Textbox(label="Text 2")
button = gr.Button("Submit")
output = gr.Textbox(label="Output")
# Listen to multiple triggers
gr.on(
triggers=[text1.change, text2.change, button.click],
fn=multi_trigger_handler,
inputs=[text1, text2],
outputs=output
)Managing persistent state across event handlers:
import gradio as gr
def increment_counter(current_count):
return current_count + 1
def reset_counter():
return 0
def update_display(count):
return f"Count: {count}"
with gr.Blocks() as demo:
counter_state = gr.State(0)
display = gr.Textbox(label="Counter", interactive=False)
increment_btn = gr.Button("Increment")
reset_btn = gr.Button("Reset")
# Increment counter and update display
increment_btn.click(
fn=increment_counter,
inputs=counter_state,
outputs=counter_state
).then(
fn=update_display,
inputs=counter_state,
outputs=display
)
# Reset counter and update display
reset_btn.click(
fn=reset_counter,
outputs=counter_state
).then(
fn=update_display,
inputs=counter_state,
outputs=display
)Control event execution performance and queuing behavior:
# Queue events for better performance
submit_btn.click(
fn=heavy_processing_function,
inputs=input_data,
outputs=output_data,
queue=True,
concurrency_limit=2 # Limit concurrent executions
)
# Batch processing for efficiency
process_btn.click(
fn=batch_processor,
inputs=batch_input,
outputs=batch_output,
batch=True,
max_batch_size=10
)Show progress indicators and status updates during event processing:
def long_running_task(progress=gr.Progress()):
progress(0, desc="Starting...")
for i in progress.tqdm(range(100)):
time.sleep(0.1) # Simulate work
return "Task completed!"
submit_btn.click(
fn=long_running_task,
outputs=result_output,
show_progress="full" # "full", "minimal", or "hidden"
)Expose event handlers as HTTP API endpoints:
def api_function(input_data):
return {"processed": input_data.upper()}
submit_btn.click(
fn=api_function,
inputs=api_input,
outputs=api_output,
api_name="process_text" # Creates /api/process_text endpoint
)Validate inputs before processing and provide user feedback:
def validate_and_process(text):
if not text or len(text) < 3:
gr.Warning("Please enter at least 3 characters")
return gr.update() # No change to output
try:
result = complex_processing(text)
gr.Success("Processing completed successfully!")
return result
except Exception as e:
gr.Error(f"Processing failed: {str(e)}")
return gr.update()Handle exceptions gracefully in event handlers:
def safe_processing(input_data):
try:
return risky_operation(input_data)
except ValueError as e:
gr.Warning(f"Invalid input: {e}")
return None
except Exception as e:
gr.Error(f"Unexpected error: {e}")
return None
# Use error handler for cleanup
submit_btn.click(
fn=safe_processing,
inputs=user_input,
outputs=result_output
).error(
fn=lambda: "Processing failed, please try again",
outputs=status_output
)Install with Tessl CLI
npx tessl i tessl/pypi-gradio