5/1/2025 Admin

Building a Dynamic Python Execution Environment: Loading Excel and Parquet files


image

In this post, we’ll explore how to build a dynamic Python execution environment using .NET MAUI, Pyodide, Monaco, and Radzen. This builds upon the concepts introduced in the article Building a Dynamic Python Execution Environment with .NET MAUI, Pyodide, Monaco, and Radzen . We’ll focus on the implementation details of the DataExample.razor and index.html files, which enable users to load data files, dynamically generate Python scripts, and execute them in a browser environment.

 

Requirements and Setup

To get started, ensure you have the following prerequisites:

  • Visual Studio 2022 (or higher)
  • .NET 9 SDK: Required to build and run the .NET MAUI project.

Clone the repository and set up the project:

  1. Clone the repository: https://github.com/BlazorData-Net/DynamicPythonDotNet/
  2. Build and run the project

 

Examine The Code

Load Data as Excel or Parquet Files

image

The DataExample.razor file allows users to upload .xls, .xlsx, or .parquet files using the <InputFile> component. The uploaded file is read into memory, converted to a Base64 string, and passed to the Pyodide virtual file system for processing.

 
<InputFile OnChange="PickAndProcessFile"
accept=".xls,.xlsx,.parquet" />
 

The PickAndProcessFile method handles the file upload:

 

private async Task PickAndProcessFile(InputFileChangeEventArgs e)  
{  
    if (e.File == null) return;  
    using var fileStream = e.File.OpenReadStream(maxAllowedSize: 100 * 1024 * 1024); // 100 MB  
    using var memoryStream = new MemoryStream();  
    await fileStream.CopyToAsync(memoryStream);  
    var base64 = Convert.ToBase64String(memoryStream.ToArray());  
    await JSRuntime.InvokeVoidAsync("writeFileToPyodide", e.File.Name, base64);  
}
 

Python Methods Using Pyodide

The index.html file includes JavaScript functions that interact with Pyodide, a Python runtime for the browser. The writeFileToPyodide function writes the uploaded file into Pyodide’s virtual file system:

 
async function writeFileToPyodide(filename, base64Data) {  
    const pyodide = await pyodideReadyPromise;  
    const bytes = base64ToUint8Array(base64Data);  
    pyodide.FS.writeFile(`/${filename}`, bytes, { encoding: 'binary' });  
}
 

The runPythonProcessing function installs necessary Python packages (e.g., pandas, openpyxl, pyarrow) and prepares the environment for processing the uploaded file.

 

Dynamically Creating Python Scripts

The C# code in DataExample.razor dynamically generates a Python script using a template. The script is displayed in the Monaco editor for user review or modification:

 
string ScriptTemplate = @"  
import pandas as pd  
import os  
def load_data():  
    filepath = '/{filename}'  
    ext = os.path.splitext(filepath)[1].lower()  
    if ext == '.parquet':  
        df = pd.read_parquet(filepath)  
    else:  
        df = pd.read_excel(filepath)  
    return df.head(10)  
";  
CurrentScript = ScriptTemplate.Replace("{filename}", CurrentFile.Name);  
await MonacoCodeEditor.UpdateCodeAsync(CurrentScript);

 

Execute Code and Display Results

image

 

The "Execute" button triggers the ExecutePython method, which runs the Python script in Pyodide and retrieves the results as JSON. The data is then displayed in a Radzen DataGrid:

 
<RadzenButton Text="Execute" Click="ExecutePython" ButtonStyle="ButtonStyle.Primary" />

 

The ExecutePython method:

 
private async Task ExecutePython()  
{  
    var pythonCode = await MonacoCodeEditor.GetCodeAsync();  
    var json = await JSRuntime.InvokeAsync<string>("runPythonScript", pythonCode);  
    var parsedArray = JsonNode.Parse(json)?.AsArray();  
    dataRows = parsedArray?.Select(item => item.AsObject().ToDictionary(k => k.Key, v => v.Value?.ToString() ?? ""))?.ToList();  
}
 

The Radzen DataGrid renders the processed data:

 
<RadzenDataGrid Data="@dataRows" TItem="Dictionary<string, object>">  
    <Columns>  
        @foreach (var key in dataRows[0].Keys)  
        {  
            <RadzenDataGridColumn TItem="Dictionary<string, object>" Title="@key">  
                <Template Context="context">  
                    @context[key]  
                </Template>  
            </RadzenDataGridColumn>  
        }  
    </Columns>  
</RadzenDataGrid>
 
image
 

Conclusion

This implementation demonstrates how to integrate .NET MAUI, Pyodide, Monaco, and Radzen to create a dynamic Python execution environment. Users can upload data files, dynamically generate Python scripts, and view the results in a user-friendly interface.

Links

An unhandled error has occurred. Reload 🗙