Back home now after what was meant to be a relaxing holiday - unfortunately, it took quite a turn with some unexpected hospital stays both overseas and after coming home.
Started
catching up and there has been some mind blowing announcements in the world of
Software Development with AI.
For ML and AI, I think we all agree that Python is the go to programming
language. Might change in the future, but at least currently that's the main
one.
I recently had a requirement where we want to use a functionality that is
written on Python to be consumed by a .NET application. The way I thought is
to expose a Python API (using Flask, FastAPI etc), but then there is going
to be a lot of data (floats) travelling through HTTP. Since I didn't have
any other option, started on that.
And then on
Microsoft Build 2025, there was this cool session on Python Meets .NET with Anthony Shaw and Scott Hanselman. It's a new project called
CSnakes, where we could use Python using .NET and most importantly that's not by
emulating or simulating Python. It's embedding Python into .NET process.
.NET and Python code shares the same threads and same memory etc.
Let's have a look at a basic working example.
Here I have a basic Python function in a file called
hello_world.py.
def say_hello(name: str) -> str:
return f"Hello {name}!"
I have now created a Console Application that targets .NET 9 and
installed CSnakes.Runtime package.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CSnakes.Runtime" Version="1.0.34" />
</ItemGroup>
</Project>
I am putting the hello_world.py inside the project and updating .csproj file to copy the .py to Output directory. And this is a very important step, this enables
CSnakes to run the source generator over Python files.
<ItemGroup>
<AdditionalFiles Include="hello_world.py">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AdditionalFiles>
</ItemGroup>
And now updating the
Program.cs as follows.
using CSnakes.Runtime;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
IHostBuilder builder = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
// Path to your Python modules
var home = Path.Join(Environment.CurrentDirectory, ".");
services
.WithPython()
.WithHome(home)
.FromRedistributable(); // Download Python 3.12 and store it locally
});
IHost app = builder.Build();
IPythonEnvironment pythonEnvironment = app.Services.GetRequiredService<IPythonEnvironment>();
// IMPORTANT: Source generated by CSnakes
IHelloWorld helloWorld = pythonEnvironment.HelloWorld();
string result = helloWorld.SayHello("John Doe");
Console.WriteLine(result); // Hello John Doe!
If you are wondering how IHelloWorld comes into the picture, it was generated at compile time.
|
Generated Source |
Now let's see how an example of how to use a Python file that uses packages. We can make use of Python pip install and requirements.txt .
First I am adding a requirements.txt file and enable copying it to the output.
<ItemGroup>
<AdditionalFiles Include="requirements.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AdditionalFiles>
</ItemGroup>
Here for the demo purposes I am adding a simple package stringcase.
stringcase
Now I am modifying the hello_world.py file as follows.
import stringcase
def say_hello(name: str) -> str:
return f"Hello {stringcase.titlecase(name)}!"
Now I am updating Program.cs the as follows.
using CSnakes.Runtime;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
IHostBuilder builder = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
// Path to your Python modules
var home = Path.Join(Environment.CurrentDirectory, ".");
services
.WithPython()
.WithHome(home)
.FromRedistributable() // Download Python 3.12 and store it locally
.WithVirtualEnvironment(Path.Join(home, ".venv"))
.WithPipInstaller(); // Optional, Installs packages listed in requirements.txt on startup
});
IHost app = builder.Build();
IPythonEnvironment pythonEnvironment =
app.Services.GetRequiredService<IPythonEnvironment>();
// Source generated by CSnakes
IHelloWorld helloWorld = pythonEnvironment.HelloWorld();
string result = helloWorld.SayHello("JohnDoe");
Console.WriteLine(result); // Hello John Doe!
|
Output |
This is pretty cool!
Watch the video:
Happy Coding.
Regards,
Jaliya
No comments:
Post a Comment