
A lightweight, AOT-compatible library that lets you call Python from C# in 4 lines — with declarative uv integration and compile-time security checks.
.NET and Python are two of the most widely used platforms in enterprise software today, yet bringing them together has always been painful. Existing interop libraries either require heavy runtime dependencies, lack support for modern .NET features like Native AOT, or demand complex project configurations with Source Generators.
If you've ever wanted to leverage Python's rich data science and ML ecosystem from a C# application — without leaving your .NET toolchain — you know the friction.
DotNetPy is my answer to that problem. Version 0.5.0 is now available on NuGet.
DotNetPy (pronounced dot-net-pie) is a .NET library for executing Python code directly from C#. It wraps the Python C API behind a clean, minimal interface.
Here's the entire "hello world":
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}");
No separate .py files. No Source Generators. No complex setup.
There are established options — pythonnet, CSnakes, IronPython. Each has strengths, but none was designed for where .NET is heading in 2025 and beyond. DotNetPy fills that gap with three design pillars:
DotNetPy is the only .NET-Python interop library that works with PublishAot=true. If you're building self-contained, ahead-of-time compiled applications, DotNetPy won't hold you back. Neither pythonnet nor CSnakes support this today.
.NET 10 introduces file-based apps — run a single .cs file with dotnet run script.cs, no project file required. DotNetPy is designed to work in this scenario from day one.
# No csproj needed
dotnet run my-analysis.cs
This makes it ideal for scripting, prototyping, and lightweight automation tasks where spinning up a full project is overkill.
Managing Python environments from .NET has always been a manual, error-prone process. DotNetPy integrates with uv, the fast Python package manager, so you can declare your entire 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 packages
var executor = project.GetExecutor();
executor.Execute("import numpy as np; print(np.mean([1,2,3]))");
One call to InitializeAsync() handles Python download, virtual environment creation, and dependency installation. No more "works on my machine" issues.
Here's a quick comparison with the existing ecosystem:
| DotNetPy | pythonnet | CSnakes | IronPython | |
|---|---|---|---|---|
| Native AOT | ✅ | ❌ | ❌ | ❌ |
| File-based Apps | ✅ | ❌ | ❌ | ❌ |
| Source Generator Required | No | No | Yes | No |
| uv Integration | Built-in | None | Supported | None |
| Bidirectional Calls | C#→Py | C#↔Py | C#→Py | C#↔Py |
| Learning Curve | Very Low | Medium | High | Low |
DotNetPy deliberately focuses on the C# → Python direction. If you need Python calling back into .NET objects, pythonnet remains the right choice. DotNetPy is for scenarios where .NET is the host and Python is the tool.
Executing dynamic code always carries risk. DotNetPy ships with a Roslyn analyzer that detects potential code injection at compile time.
// ❌ The analyzer flags this — user input as code
executor.Execute(userInput);
// ✅ Safe — user data passed as variables
executor.Execute(
"result = sum(numbers)",
new Dictionary<string, object?> { { "numbers", userNumbers } }
);
This is a deliberate design choice: make the safe path easy and the dangerous path visible.
--disable-gilInstall from NuGet:
dotnet add package DotNetPy --version 0.5.0
Initialize and run:
using DotNetPy;
Python.Initialize("/path/to/python313.dll");
var executor = Python.GetInstance();
var sum = executor.Evaluate("sum([1,2,3,4,5])")?.GetInt32();
Console.WriteLine(sum); // 15
Or let DotNetPy find Python automatically:
Python.Initialize(PythonDiscovery.FindPython());
.NET 10 file-based apps as Python-capable scriptsThe roadmap includes embeddable Python support on Windows (for simplified deployment) and specialized optimizations for AI and data science workflows. This is v0.5.0 — the API is stabilizing, and feedback at this stage is especially valuable.
If you're a .NET developer who's been eyeing Python's ecosystem, give DotNetPy a try. Issues, stars, and feedback are all welcome.
gemmaI ported the whole Gemma-4 family — E2B, E4B, 12B, 31B, and the 26B-A4B MoE — to run on...
communityHey DEV, I'm Tobore. Let's actually connect. I've been on here for a while now, mostly writing and...
ai(yep, kinda clickbait, just for the funsies 😊) At the beginning of the year, I relaunched my...
aiMy laptop was sitting idle with the fan at full tilt. Nothing was running that I knew of. The culprit...
githubactionsI Built a Thing! TL;DR — Google Gemini-based Pull Request reviews and Issue Triaging for...
aiI've been hearing the word "harness" thrown around a lot lately. I assumed it just meant "the IDE" or...
Workflows from the Neura Market marketplace related to this DeepSeek resource