Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Python

Pythonnet – A Simple Union of .NET Core and Python You’ll Love

5.00/5 (10 votes)
25 Jan 2023CPOL3 min read 26.8K  
Use the Python for .NET package as a way to call Python from C# code
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:

C#
using Python.Runtime;

internal sealed class Program
{
    private static void Main(string[] args)
    {
        // NOTE: set this based on your python install. this will resolve from
        // your PATH environment variable as well.
        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:

C#
using System;
using Python.Runtime;

internal sealed class Program
{
    private static void Main(string[] args)
    {
        // NOTE: set this based on your python install. this will resolve from
        // your PATH environment variable as well.
        Runtime.PythonDLL = "python310.dll";

        PythonEngine.Initialize();
        using (Py.GIL())
        {
            // NOTE: this doesn't validate input
            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.

A calculator output using Pythonnet

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:

C#
using Python.Runtime;

internal sealed class Program
{
    private static void Main(string[] args)
    {
        // NOTE: Set this based on your Python install. 
        // This will resolve from your PATH environment variable as well.
        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!

A list output using Pythonnet

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?!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)