import gradio as gr import tempfile import os import sys import subprocess import time import random import string import signal import atexit # Set environment variable to avoid matplotlib issues os.environ['MPLCONFIGDIR'] = '/tmp' # Create a temp directory for our app files TEMP_DIR = os.path.join(tempfile.gettempdir(), "gradio_apps") os.makedirs(TEMP_DIR, exist_ok=True) # Track running processes running_process = None current_port = None current_file = None # Cleanup function to ensure we don't leave processes running def cleanup(): global running_process, current_file if running_process and running_process.poll() is None: try: running_process.terminate() running_process.wait(timeout=5) except: running_process.kill() if current_file and os.path.exists(current_file): try: os.unlink(current_file) except: pass # Register cleanup atexit.register(cleanup) # Example Gradio app codes to choose from EXAMPLE_APPS = { "hello_world": """ import gradio as gr def greet(name): return f"Hello, {name}!" demo = gr.Interface( fn=greet, inputs=gr.Textbox(label="Your Name"), outputs=gr.Textbox(label="Greeting"), title="Hello World App", description="A simple greeting app" ) # Launch on specified port demo.launch(server_name="0.0.0.0", server_port=PORT) """, "calculator": """ import gradio as gr def calculate(num1, num2, operation): if operation == "Add": return num1 + num2 elif operation == "Subtract": return num1 - num2 elif operation == "Multiply": return num1 * num2 elif operation == "Divide": if num2 == 0: return "Error: Division by zero" return num1 / num2 demo = gr.Interface( fn=calculate, inputs=[ gr.Number(label="First Number"), gr.Number(label="Second Number"), gr.Radio(["Add", "Subtract", "Multiply", "Divide"], label="Operation") ], outputs=gr.Textbox(label="Result"), title="Calculator App", description="Perform basic arithmetic operations" ) # Launch on specified port demo.launch(server_name="0.0.0.0", server_port=PORT) """, "image_filter": """ import gradio as gr import numpy as np from PIL import Image def apply_filter(image, filter_type): if image is None: return None img_array = np.array(image) if filter_type == "Grayscale": result = np.mean(img_array, axis=2).astype(np.uint8) return Image.fromarray(result) elif filter_type == "Invert": result = 255 - img_array return Image.fromarray(result) elif filter_type == "Sepia": sepia = np.array([[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]) sepia_img = img_array.dot(sepia.T) sepia_img[sepia_img > 255] = 255 return Image.fromarray(sepia_img.astype(np.uint8)) return image demo = gr.Interface( fn=apply_filter, inputs=[ gr.Image(type="pil"), gr.Radio(["Grayscale", "Invert", "Sepia"], label="Filter") ], outputs=gr.Image(type="pil"), title="Image Filter App", description="Apply different filters to your images" ) # Launch on specified port demo.launch(server_name="0.0.0.0", server_port=PORT) """ } # Function to find an available port def find_available_port(start=7870): import socket port = start while True: try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(('localhost', port)) return port except OSError: port += 1 # Function to run a Gradio app as a subprocess def run_app(app_code, port): global running_process, current_file # Stop any existing app stop_app() # Replace PORT in the code app_code = app_code.replace("PORT", str(port)) # Create a temporary file fd, filepath = tempfile.mkstemp(suffix='.py', dir=TEMP_DIR) os.close(fd) with open(filepath, 'w') as f: f.write(app_code) # Store the current file path current_file = filepath # Run the app try: process = subprocess.Popen( [sys.executable, filepath], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # Store the process running_process = process # Wait a moment for the app to start time.sleep(2) # Check if the process is still running if process.poll() is not None: # Process failed to start stdout, stderr = process.communicate() error_msg = f"App failed to start: {stderr.decode('utf-8')}" return None, error_msg return port, None except Exception as e: return None, f"Error starting app: {str(e)}" # Function to stop the running app def stop_app(): global running_process, current_file if running_process and running_process.poll() is None: running_process.terminate() try: running_process.wait(timeout=5) except: running_process.kill() if current_file and os.path.exists(current_file): try: os.unlink(current_file) except: pass running_process = None current_file = None # Function to select an app based on description def select_app(description): description = description.lower() if "hello" in description or "greet" in description: return EXAMPLE_APPS["hello_world"] elif "calculat" in description or "math" in description or "arithmetic" in description: return EXAMPLE_APPS["calculator"] elif "image" in description or "filter" in description or "photo" in description: return EXAMPLE_APPS["image_filter"] else: # Default to hello world return EXAMPLE_APPS["hello_world"] # Main Gradio interface with gr.Blocks(title="Gradio App Generator") as demo: gr.Markdown("# 🔄 Dynamic Gradio App Generator") gr.Markdown("Select an app type to generate and run it dynamically") with gr.Row(): with gr.Column(scale=1): # Input area app_description = gr.Textbox( label="App Description", placeholder="Describe the app you want to generate...", lines=3, value="A calculator app that performs basic arithmetic" ) # Example buttons with gr.Row(): hello_btn = gr.Button("Hello World") calc_btn = gr.Button("Calculator") image_btn = gr.Button("Image Filter") # Generate and stop buttons with gr.Row(): generate_btn = gr.Button("Generate & Run App", variant="primary") stop_btn = gr.Button("Stop App", variant="stop") # Code display with gr.Accordion("Generated Code", open=False): code_display = gr.Code(language="python") # Status message status_msg = gr.Markdown("") with gr.Column(scale=2): # Preview area app_frame = gr.HTML("
App will appear here
Enter a description first
Failed to start app:
{error}
App stopped