Introducing Gradio 5.0
Read MoreIntroducing Gradio 5.0
Read MoreThe core gradio
library is a Python library. But you can also use gradio
to create UIs around programs written in other languages, thanks to Python's ability to interface with external processes. Using Python's subprocess
module, you can call programs written in C++, Rust, or virtually any other language, allowing gradio
to become a flexible UI layer for non-Python applications.
In this post, we'll walk through how to integrate gradio
with C++ and Rust, using Python's subprocess
module to invoke code written in these languages. We'll also discuss how to use Gradio with R, which is even easier, thanks to the reticulate R package, which makes it possible to install and import Python modules in R.
Let’s start with a simple example of integrating a C++ program into a Gradio app. Suppose we have the following C++ program that adds two numbers:
// add.cpp
#include <iostream>
int main() {
double a, b;
std::cin >> a >> b;
std::cout << a + b << std::endl;
return 0;
}
This program reads two numbers from standard input, adds them, and outputs the result.
We can build a Gradio interface around this C++ program using Python's subprocess
module. Here’s the corresponding Python code:
import gradio as gr
import subprocess
def add_numbers(a, b):
process = subprocess.Popen(
['./add'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
output, error = process.communicate(input=f"{a} {b}\n".encode())
if error:
return f"Error: {error.decode()}"
return float(output.decode().strip())
demo = gr.Interface(
fn=add_numbers,
inputs=[gr.Number(label="Number 1"), gr.Number(label="Number 2")],
outputs=gr.Textbox(label="Result")
)
demo.launch()
Here, subprocess.Popen
is used to execute the compiled C++ program (add
), pass the input values, and capture the output. You can compile the C++ program by running:
g++ -o add add.cpp
This example shows how easy it is to call C++ from Python using subprocess
and build a Gradio interface around it.
Now, let’s move to another example: calling a Rust program to apply a sepia filter to an image. The Rust code could look something like this:
// sepia.rs
extern crate image;
use image::{GenericImageView, ImageBuffer, Rgba};
fn sepia_filter(input: &str, output: &str) {
let img = image::open(input).unwrap();
let (width, height) = img.dimensions();
let mut img_buf = ImageBuffer::new(width, height);
for (x, y, pixel) in img.pixels() {
let (r, g, b, a) = (pixel[0] as f32, pixel[1] as f32, pixel[2] as f32, pixel[3]);
let tr = (0.393 * r + 0.769 * g + 0.189 * b).min(255.0);
let tg = (0.349 * r + 0.686 * g + 0.168 * b).min(255.0);
let tb = (0.272 * r + 0.534 * g + 0.131 * b).min(255.0);
img_buf.put_pixel(x, y, Rgba([tr as u8, tg as u8, tb as u8, a]));
}
img_buf.save(output).unwrap();
}
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() != 3 {
eprintln!("Usage: sepia <input_file> <output_file>");
return;
}
sepia_filter(&args[1], &args[2]);
}
This Rust program applies a sepia filter to an image. It takes two command-line arguments: the input image path and the output image path. You can compile this program using:
cargo build --release
Now, we can call this Rust program from Python and use Gradio to build the interface:
import gradio as gr
import subprocess
def apply_sepia(input_path):
output_path = "output.png"
process = subprocess.Popen(
['./target/release/sepia', input_path, output_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
process.wait()
return output_path
demo = gr.Interface(
fn=apply_sepia,
inputs=gr.Image(type="filepath", label="Input Image"),
outputs=gr.Image(label="Sepia Image")
)
demo.launch()
Here, when a user uploads an image and clicks submit, Gradio calls the Rust binary (sepia
) to process the image, and returns the sepia-filtered output to Gradio.
This setup showcases how you can integrate performance-critical or specialized code written in Rust into a Gradio interface.
reticulate
)Integrating Gradio with R is particularly straightforward thanks to the reticulate
package, which allows you to run Python code directly in R. Let’s walk through an example of using Gradio in R.
Installation
First, you need to install the reticulate
package in R:
install.packages("reticulate")
Once installed, you can use the package to run Gradio directly from within an R script.
library(reticulate)
py_install("gradio", pip = TRUE)
gr <- import("gradio") # import gradio as gr
Building a Gradio Application
With gradio installed and imported, we now have access to gradio's app building methods. Let's build a simple app for an R function that returns a greeting
greeting <- \(name) paste("Hello", name)
app <- gr$Interface(
fn = greeting,
inputs = gr$Text(label = "Name"),
outputs = gr$Text(label = "Greeting"),
title = "Hello! 😃 👋"
)
app$launch(server_name = "localhost",
server_port = as.integer(3000))
Credit to @IfeanyiIdiaye for contributing this section. You can see more examples here, including using Gradio Blocks to build a machine learning application in R.