Python package installation and management within the WebAssembly environment. Provides support for installing packages from PyPI and managing dependencies in the isolated worker environment.
Install Python packages in the worker environment using the standard package installation interface.
/**
* Install Python packages in the worker environment
* @param requirements - Array of package names to install (supports pip syntax)
* @returns Promise that resolves when packages are installed
*/
install(requirements: string[]): Promise<void>;Usage Examples:
import { WorkerProxy } from "@gradio/wasm";
const worker = new WorkerProxy({
gradioWheelUrl: "https://example.com/gradio.whl",
gradioClientWheelUrl: "https://example.com/gradio_client.whl",
files: {},
requirements: [], // Can specify initial requirements here
sharedWorkerMode: false
});
worker.addEventListener("initialization-completed", async () => {
// Install basic data science packages
await worker.install([
"numpy>=1.21.0",
"pandas>=1.3.0",
"matplotlib>=3.4.0",
"scikit-learn>=1.0.0"
]);
// Install packages with specific versions
await worker.install([
"requests==2.28.1",
"pillow==9.2.0"
]);
// Install packages from different sources
await worker.install([
"scipy", // Latest version
"tensorflow==2.9.0", // Specific version
"torch>=1.12.0,<2.0.0" // Version range
]);
// Install development tools
await worker.install([
"pytest",
"black",
"flake8"
]);
// Verify installations
await worker.runPythonCode(`
import sys
import pkg_resources
print("Installed packages:")
installed_packages = [d for d in pkg_resources.working_set]
for package in sorted(installed_packages, key=lambda x: x.project_name):
print(f" {package.project_name}: {package.version}")
print(f"\\nPython version: {sys.version}")
print(f"Python path: {sys.path}")
`);
});Packages can be specified during worker initialization for automatic installation:
import { WorkerProxy } from "@gradio/wasm";
// Specify requirements during initialization
const worker = new WorkerProxy({
gradioWheelUrl: "https://example.com/gradio.whl",
gradioClientWheelUrl: "https://example.com/gradio_client.whl",
files: {
"requirements.txt": {
data: `
numpy>=1.21.0
pandas>=1.3.0
matplotlib>=3.4.0
scikit-learn>=1.0.0
requests==2.28.1
pillow==9.2.0
`.trim(),
opts: { encoding: "utf8" }
}
},
requirements: [
"numpy>=1.21.0",
"pandas>=1.3.0",
"matplotlib>=3.4.0",
"scikit-learn>=1.0.0",
"requests==2.28.1",
"pillow==9.2.0"
],
sharedWorkerMode: false
});
worker.addEventListener("initialization-completed", async () => {
// Packages are already installed and ready to use
await worker.runPythonCode(`
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
import requests
from PIL import Image
print("All packages successfully imported!")
# Demonstrate package functionality
data = np.random.randn(100, 5)
df = pd.DataFrame(data, columns=['A', 'B', 'C', 'D', 'E'])
print(f"Created DataFrame with shape: {df.shape}")
# Create a simple plot
plt.figure(figsize=(8, 6))
plt.plot(df['A'])
plt.title("Sample Data Plot")
plt.savefig("sample_plot.png")
print("Plot saved to sample_plot.png")
# Initialize ML model
model = RandomForestClassifier(n_estimators=10)
print(f"Created model: {type(model).__name__}")
`);
});Install packages dynamically based on user requirements or runtime conditions:
import { WorkerProxy } from "@gradio/wasm";
class DynamicPackageManager {
private worker: WorkerProxy;
private installedPackages: Set<string> = new Set();
constructor(options: WorkerProxyOptions) {
this.worker = new WorkerProxy(options);
this.setupWorker();
}
private setupWorker() {
this.worker.addEventListener("initialization-completed", () => {
console.log("Worker ready for dynamic package management");
this.trackInstalledPackages();
});
}
private async trackInstalledPackages() {
// Get list of initially installed packages
await this.worker.runPythonCode(`
import pkg_resources
installed = [d.project_name for d in pkg_resources.working_set]
print("INSTALLED_PACKAGES:", ",".join(installed))
`);
// In a real implementation, you'd parse the stdout to get the package list
// For now, we'll track packages as we install them
}
async installIfNeeded(packages: string[]): Promise<string[]> {
const packagesToInstall = packages.filter(pkg => {
const packageName = pkg.split(/[>=<!=]/)[0];
return !this.installedPackages.has(packageName);
});
if (packagesToInstall.length === 0) {
console.log("All packages already installed");
return [];
}
console.log(`Installing new packages: ${packagesToInstall.join(", ")}`);
await this.worker.install(packagesToInstall);
// Track newly installed packages
packagesToInstall.forEach(pkg => {
const packageName = pkg.split(/[>=<!=]/)[0];
this.installedPackages.add(packageName);
});
return packagesToInstall;
}
async installForWorkflow(workflowType: string): Promise<void> {
const workflows = {
"data-analysis": [
"numpy>=1.21.0",
"pandas>=1.3.0",
"matplotlib>=3.4.0",
"seaborn>=0.11.0",
"plotly>=5.0.0"
],
"machine-learning": [
"numpy>=1.21.0",
"pandas>=1.3.0",
"scikit-learn>=1.0.0",
"xgboost>=1.6.0",
"lightgbm>=3.3.0"
],
"deep-learning": [
"numpy>=1.21.0",
"torch>=1.12.0",
"torchvision>=0.13.0",
"transformers>=4.20.0"
],
"web-scraping": [
"requests>=2.28.0",
"beautifulsoup4>=4.11.0",
"lxml>=4.9.0",
"selenium>=4.3.0"
],
"image-processing": [
"numpy>=1.21.0",
"pillow>=9.2.0",
"opencv-python>=4.6.0",
"scikit-image>=0.19.0"
]
};
const packages = workflows[workflowType];
if (!packages) {
throw new Error(`Unknown workflow type: ${workflowType}`);
}
const installed = await this.installIfNeeded(packages);
console.log(`Workflow '${workflowType}' ready. Installed: ${installed.length} new packages`);
}
async checkPackageCompatibility(packages: string[]): Promise<boolean> {
// Check if packages can be installed together
try {
await this.worker.runPythonCode(`
import pkg_resources
import sys
packages_to_check = ${JSON.stringify(packages)}
print(f"Checking compatibility for: {packages_to_check}")
# This is a simplified compatibility check
# In practice, you might want to use pip's dependency resolver
for package in packages_to_check:
try:
# Try to parse the requirement
req = pkg_resources.Requirement.parse(package)
print(f"✓ {package} - valid requirement")
except Exception as e:
print(f"✗ {package} - invalid requirement: {e}")
sys.exit(1)
print("All packages appear compatible")
`);
return true;
} catch (error) {
console.error("Package compatibility check failed:", error);
return false;
}
}
getInstalledPackages(): Set<string> {
return new Set(this.installedPackages);
}
}
// Usage
const packageManager = new DynamicPackageManager({
gradioWheelUrl: "https://example.com/gradio.whl",
gradioClientWheelUrl: "https://example.com/gradio_client.whl",
files: {},
requirements: ["numpy"], // Minimal initial requirements
sharedWorkerMode: false
});
// Install packages for specific workflows
await packageManager.installForWorkflow("data-analysis");
await packageManager.installForWorkflow("machine-learning");
// Check what's installed
console.log("Installed packages:", Array.from(packageManager.getInstalledPackages()));Handle package versions and conflicts:
import { WorkerProxy } from "@gradio/wasm";
class VersionManager {
private worker: WorkerProxy;
constructor(worker: WorkerProxy) {
this.worker = worker;
}
async getPackageVersion(packageName: string): Promise<string | null> {
try {
await this.worker.runPythonCode(`
import pkg_resources
try:
version = pkg_resources.get_distribution("${packageName}").version
print(f"PACKAGE_VERSION:{packageName}:{version}")
except pkg_resources.DistributionNotFound:
print(f"PACKAGE_VERSION:{packageName}:NOT_FOUND")
`);
// In a real implementation, parse stdout to get the version
return "unknown"; // Placeholder
} catch (error) {
return null;
}
}
async upgradePackage(packageName: string, targetVersion?: string): Promise<void> {
const packageSpec = targetVersion ? `${packageName}==${targetVersion}` : packageName;
console.log(`Upgrading ${packageName}${targetVersion ? ` to ${targetVersion}` : " to latest"}`);
await this.worker.install([packageSpec]);
const newVersion = await this.getPackageVersion(packageName);
console.log(`${packageName} upgraded to version: ${newVersion}`);
}
async checkForUpdates(packages: string[]): Promise<Record<string, { current: string; latest: string }>> {
const updates: Record<string, { current: string; latest: string }> = {};
await this.worker.runPythonCode(`
import pkg_resources
import json
packages_to_check = ${JSON.stringify(packages)}
update_info = {}
for package_name in packages_to_check:
try:
current_version = pkg_resources.get_distribution(package_name).version
# In a real implementation, you would check PyPI for the latest version
# For now, we'll just report the current version
update_info[package_name] = {
"current": current_version,
"latest": current_version # Placeholder
}
except pkg_resources.DistributionNotFound:
update_info[package_name] = {
"current": "NOT_INSTALLED",
"latest": "UNKNOWN"
}
print("UPDATE_INFO:" + json.dumps(update_info))
`);
// In a real implementation, parse stdout to get update info
return updates;
}
}Robust error handling for package installation issues:
import { WorkerProxy } from "@gradio/wasm";
class RobustPackageInstaller {
private worker: WorkerProxy;
private installationLog: Array<{ package: string; success: boolean; error?: string }> = [];
constructor(worker: WorkerProxy) {
this.worker = worker;
}
async installWithRetry(packages: string[], maxRetries = 3): Promise<void> {
for (const packageSpec of packages) {
let success = false;
let lastError: any = null;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
console.log(`Installing ${packageSpec} (attempt ${attempt}/${maxRetries})`);
await this.worker.install([packageSpec]);
success = true;
this.installationLog.push({ package: packageSpec, success: true });
console.log(`✓ Successfully installed ${packageSpec}`);
break;
} catch (error) {
lastError = error;
console.warn(`✗ Failed to install ${packageSpec} (attempt ${attempt}): ${error}`);
if (attempt < maxRetries) {
const delay = 1000 * Math.pow(2, attempt - 1); // Exponential backoff
console.log(`Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
if (!success) {
this.installationLog.push({
package: packageSpec,
success: false,
error: lastError?.toString()
});
console.error(`Failed to install ${packageSpec} after ${maxRetries} attempts`);
}
}
}
async validateInstallation(packages: string[]): Promise<string[]> {
const failedPackages: string[] = [];
await this.worker.runPythonCode(`
import pkg_resources
packages_to_validate = ${JSON.stringify(packages.map(pkg => pkg.split(/[>=<!=]/)[0]))}
failed_imports = []
for package_name in packages_to_validate:
try:
pkg_resources.get_distribution(package_name)
print(f"✓ {package_name} is installed")
except pkg_resources.DistributionNotFound:
print(f"✗ {package_name} is NOT installed")
failed_imports.append(package_name)
if failed_imports:
print(f"FAILED_PACKAGES: {','.join(failed_imports)}")
else:
print("All packages validated successfully")
`);
// In a real implementation, parse stdout to get failed packages
return failedPackages;
}
getInstallationLog(): Array<{ package: string; success: boolean; error?: string }> {
return [...this.installationLog];
}
printInstallationSummary(): void {
const successful = this.installationLog.filter(log => log.success).length;
const failed = this.installationLog.filter(log => !log.success).length;
console.log(`\nInstallation Summary:`);
console.log(` ✓ Successful: ${successful}`);
console.log(` ✗ Failed: ${failed}`);
if (failed > 0) {
console.log(`\nFailed installations:`);
this.installationLog
.filter(log => !log.success)
.forEach(log => {
console.log(` - ${log.package}: ${log.error}`);
});
}
}
}
// Usage
const worker = new WorkerProxy(options);
const installer = new RobustPackageInstaller(worker);
worker.addEventListener("initialization-completed", async () => {
const packages = [
"numpy>=1.21.0",
"pandas>=1.3.0",
"matplotlib>=3.4.0",
"invalid-package-name", // This will fail
"scikit-learn>=1.0.0"
];
await installer.installWithRetry(packages);
const failedPackages = await installer.validateInstallation(packages);
if (failedPackages.length > 0) {
console.warn("Some packages failed to install:", failedPackages);
}
installer.printInstallationSummary();
});