Python and C# are two very popular languages. As a C# developer primarily, I find there are situations where I would like to interface with Python. Here are examples for using the Python for .NET package as a way to call Python from C# code.
Python is a powerful and versatile programming language that has become increasingly popular. For many, it’s one of the very first programming languages they pick up when getting started. Some of the highest traffic posts on my blog many years after they were written look at using C# and Python together. Today, we’re going to explore how you can use Python from inside a C# .NET Core application with much more modern approaches than my original articles. Enter Pythonnet!
Pythonnet Package & Getting Started
We’re going to be looking at Python for .NET in order to accomplish this goal. This library allows you to take advantage of Python installed on the running machine from within your .NET Core applications. You must configure it to point at the corresponding Python DLL that you’d like to use, and after a couple of lines of initialization, you’re off to the races!
Example 1 – Hello World with Pythonnet
To get started, you’ll need to install the pythonnet package from NuGet. Once you’ve done that, you can use the following code to run a Python script from your C# code:
using Python.Runtime;
internal sealed class Program
{
private static void Main(string[] args)
{
Runtime.PythonDLL = "python310.dll";
PythonEngine.Initialize();
using (Py.GIL())
{
using var scope = Py.CreateScope();
scope.Exec("print('Hello World from Python!')");
}
}
}
This code sets our python DLL path on the Runtime, which will be a necessary step. Don’t forget to do this! We must then call PythonEngine.Initialize()
and Py.GIL()
, which we will want to dispose of later so consider a using
statement. We can ask the static
Py
class to create a scope for us to use, and then leverage the Exec method in order to execute some Python code. In this example, we’re calling the Exec method to run a simple Python script that prints “Hello World from Python!
” to the console.
Example 2 – A Pythonnet Calculator!
You can also use the Python C API to call Python functions directly from C# code. To do this, you’ll need to create a C# wrapper for the Python function you want to call. Here’s an example of how you might create a wrapper for a Python function that takes two integers as arguments and returns their sum:
using System;
using Python.Runtime;
internal sealed class Program
{
private static void Main(string[] args)
{
Runtime.PythonDLL = "python310.dll";
PythonEngine.Initialize();
using (Py.GIL())
{
Console.WriteLine("Enter first integer:");
var firstInt = int.Parse(Console.ReadLine());
Console.WriteLine("Enter second integer:");
var secondInt = int.Parse(Console.ReadLine());
using dynamic scope = Py.CreateScope();
scope.Exec("def add(a, b): return a + b");
var sum = scope.add(firstInt, secondInt);
Console.WriteLine($"Sum: {sum}");
}
}
}
In this example, we’re using the Exec method to define a Python function called add
that takes two integers as arguments and returns their sum
. Thanks to the dynamic keyword in C#, we are able to make an assumption that our scope
object has a method called add
directly on it. Finally, we use C# code directly to call the add
method just like as if it was inside of C#. The return type assigned to the sum
variable in C# is also dynamic, but you could declare this variable as an integer and it will compile properly with this type as well.
The results in the console window from our simple Pythonnet calculator!
Example 3 – Object Interop
We can also pass Python objects to C# functions and vice versa. Here’s an example of how you might receive a Python list back to C# function and iterate over its elements without using the dynamic keyword:
using Python.Runtime;
internal sealed class Program
{
private static void Main(string[] args)
{
Runtime.PythonDLL = "python310.dll";
PythonEngine.Initialize();
using (Py.GIL())
{
using var scope = Py.CreateScope();
scope.Exec("number_list = [1, 2, 3, 4, 5]");
var pythonListObj = scope.Eval("number_list");
var csharpListObj = pythonListObj.As<int[]>();
Console.WriteLine("The numbers from python are:");
foreach (var value in csharpListObj)
{
Console.WriteLine(value);
}
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
}
}
}
In this example, we’re using the Exec method to create a Python list and assign it to a variable called number_list
. We then use the Eval method to get a reference to the list
object and then we can call As<T>
with an integer array (denoted as int[]
) to convert the result. At this point, csharpListObj
is a fully functional C# array with the array of integers from Python. And to prove it, we can list them all to the console!
The numbers printed to the console are declared in Python and passed back to C# from Pythonnet.
Summary
In conclusion, using Python inside C# .NET Core application is easy and seamless. Python for .NET provides many methods for interacting with the Python interpreter and calling Python functions. By using these methods, you can leverage the power of Python to add new functionality in your C# .NET Core applications. What are you going to build?!