Python interop, reimagined for modern .NET β¨
// .NET β Python in 4 lines
var executor = Python.GetInstance();
var temperatures = new[] { 23.5, 19.2, 31.8, 27.4, 22.1 };
using var result = executor.ExecuteAndCapture(@"
import statistics
result = {'mean': statistics.mean(data), 'stdev': statistics.stdev(data)}
", new Dictionary<string, object?> { { "data", temperatures } });
Console.WriteLine($"Mean: {result?.GetDouble("mean"):F1}Β°C Β± {result?.GetDouble("stdev"):F1}");β Native AOT Support | β .NET 10 File-based Apps | β Declarative uv Integration | β Built-in Security
DotNetPy (pronounced dot-net-pie) is a .NET library that allows you to seamlessly execute Python code directly from your C# applications. It provides a simple and intuitive API to run Python scripts and evaluate expressions with minimal boilerplate.
| Document | Description |
|---|---|
| Usage Examples | Detailed code examples and patterns |
| Security Guide | Security considerations and safe usage |
| uv Integration | Declarative Python environment management |
| Performance | Thread safety and concurrency characteristics |
| Comparison | How DotNetPy compares to pythonnet and CSnakes |
| Testing | Running integration tests |
| Code Samples | Runnable sample applications |
DotNetPy is built around three core principles:
Write Python code as strings within your C# code, with full control over execution and data flow. No separate Python files, no Source Generators, no complex setup β just define your Python logic inline and execute it.
// Define and execute Python declaratively from C#
using var result = executor.ExecuteAndCapture(@"
import statistics
result = {'mean': statistics.mean(data), 'stdev': statistics.stdev(data)}
", new Dictionary<string, object?> { { "data", myNumbers } });Designed from the ground up for modern .NET scenarios:
- File-based Apps (.NET 10+): Works perfectly with
dotnet run script.csβ no project file required - Native AOT: The only .NET-Python interop library that supports
PublishAot=true - Minimal Dependencies: No heavy runtime requirements
# Just run it β no csproj needed
dotnet run my-script.csDeclaratively manage Python environments using uv:
// Define your Python environment in C#
using var project = PythonProject.CreateBuilder()
.WithProjectName("my-analysis")
.WithPythonVersion(">=3.10")
.AddDependencies("numpy>=1.24.0", "pandas>=2.0.0")
.Build();
await project.InitializeAsync(); // Downloads Python, creates venv, installs packagesDotNetPy executes arbitrary Python code with the same privileges as the host .NET process. Never pass untrusted or user-provided input directly to execution methods.
// β DANGEROUS: User input executed as code
executor.Execute(userInput); // Remote Code Execution vulnerability!
// β
SAFE: User data passed as variables, not code
executor.Execute("result = sum(numbers)", new Dictionary<string, object?> { { "numbers", userNumbers } });DotNetPy includes a built-in Roslyn analyzer that detects potential code injection at compile time.
- Automatic Python Discovery: Cross-platform automatic detection of installed Python distributions with configurable requirements (version, architecture).
- Runtime Information: Query and inspect the currently active Python runtime configuration.
- Execute Python Code: Run multi-line Python scripts.
- Evaluate Expressions: Directly evaluate single-line Python expressions and get the result.
- Data Marshaling:
- Pass complex .NET objects (like arrays and dictionaries) to Python.
- Convert Python objects (including dictionaries, lists, numbers, and strings) back into .NET types.
- Variable Management:
ExecuteAndCapture: Execute code and capture a specific variable (by convention,result) into a .NET object.CaptureVariable(s): Capture one or more global variables from the Python session after execution.DeleteVariable(s): Remove variables from the Python session.VariableExists: Check if a variable exists in the Python session.GetExistingVariables: Returns a list of variables that actually exist from a given list of variable names.ClearGlobals: Clear all global variables from the Python session.
- Free-threaded Python Support: Detects and reports Python 3.13+ builds with
--disable-gil(experimental free-threading). - No Boilerplate: The library handles the complexities of the Python C API, providing a clean interface.
- .NET 8.0 or later.
- A Python installation (e.g., Python 3.13). You will need the path to the Python shared library (
pythonXX.dllon Windows,libpythonX.X.soon Linux). - (Optional) uv for declarative environment management.
To start using DotNetPy, you need to initialize the Python engine with the path to your Python library.
using DotNetPy;
// Path to your Python shared library
var pythonLibraryPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Programs", "Python", "Python313", "python313.dll");
// Initialize the Python engine
Python.Initialize(pythonLibraryPath);
// Get an executor instance
var executor = Python.GetInstance();// Evaluate expressions
var sum = executor.Evaluate("sum([1,2,3,4,5])")?.GetInt32(); // 15
// Execute scripts and capture results
using var result = executor.ExecuteAndCapture(@"
import math
result = {'sqrt': math.sqrt(16), 'pi': math.pi}
");
Console.WriteLine(result?.GetDouble("sqrt")); // 4
// Pass .NET data to Python
var numbers = new[] { 10, 20, 30 };
using var stats = executor.ExecuteAndCapture(@"
result = {'sum': sum(data), 'avg': sum(data)/len(data)}
", new Dictionary<string, object?> { { "data", numbers } });Wondering how DotNetPy compares to pythonnet or CSnakes? Check out our detailed comparison guide to understand the differences and choose the right tool for your needs.
DotNetPy is thread-safe through Python's Global Interpreter Lock (GIL). Best suited for sequential execution, I/O-bound operations, and low-to-moderate concurrency scenarios.
π Performance & Concurrency Details β
Declaratively manage Python environments using uv:
using DotNetPy;
using DotNetPy.Uv;
// Define your Python project declaratively
using var project = PythonProject.CreateBuilder()
.WithProjectName("my-data-analysis")
.WithPythonVersion(">=3.10")
.AddDependency("numpy", ">=1.24.0")
.AddDependency("pandas", ">=2.0.0")
.Build();
await project.InitializeAsync(); // Downloads Python, creates venv, installs packages
var executor = project.GetExecutor();
executor.Execute("import numpy as np; print(np.mean([1,2,3]))");π Full uv Integration Guide β
Ready-to-run sample applications are available in the samples/ directory:
| Sample | Description |
|---|---|
| quickstart | Minimal example - .NET β Python data flow |
| uv-integration | Comprehensive test with uv-managed Python |
| declarative-python | Declarative environment setup with PythonProjectBuilder |
# Run the quickstart sample
cd samples/quickstart
dotnet run quickstart.csπ All Samples β
π Testing Guide β
The following features are planned for future releases:
- β Automatic Python Discovery (Completed): Cross-platform automatic detection and discovery of installed Python distributions, eliminating the need for manual library path configuration.
- β
Virtual Environment (venv) Support (Completed): Enhanced support for working with Python virtual environments, including automatic activation and package management via
LoadVirtualEnvironment()extension method. - β
uv Integration (Completed): Declarative Python environment management using the uv package manager with
PythonProjectandPythonProjectBuilderclasses. - Embeddable Python Support (Windows): Automatic setup and configuration of embeddable Python packages on Windows for simplified deployment scenarios.
- AI and Data Science Scenarios: Specialized support and optimizations for AI and data science workflows, including better integration with popular libraries like NumPy, Pandas, and machine learning frameworks.
This project is licensed under the Apache License 2.0. Please see the LICENSE.txt file for details.
