5/1/2025 Admin
Building a Dynamic Python Execution Environment: Loading Excel and Parquet files
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:
- Clone the repository: https://github.com/BlazorData-Net/DynamicPythonDotNet/
- Build and run the project
Examine The Code
Load Data as Excel or Parquet Files
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 MBusing 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 pdimport osdef 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
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>
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.