Click here to Skip to main content
15,867,488 members
Articles / Programming Languages / Python

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

Rate me:
Please Sign up or sign in to vote.
5.00/5 (10 votes)
25 Jan 2023CPOL3 min read 17.7K   18   15
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)


Written By
Team Leader Microsoft
United States United States
I'm a software engineering professional with a decade of hands-on experience creating software and managing engineering teams. I graduated from the University of Waterloo in Honours Computer Engineering in 2012.

I started blogging at http://www.devleader.ca in order to share my experiences about leadership (especially in a startup environment) and development experience. Since then, I have been trying to create content on various platforms to be able to share information about programming and engineering leadership.

My Social:
YouTube: https://youtube.com/@DevLeader
TikTok: https://www.tiktok.com/@devleader
Blog: http://www.devleader.ca/
GitHub: https://github.com/ncosentino/
Twitch: https://www.twitch.tv/ncosentino
Twitter: https://twitter.com/DevLeaderCa
Facebook: https://www.facebook.com/DevLeaderCa
Instagram:
https://www.instagram.com/dev.leader
LinkedIn: https://www.linkedin.com/in/nickcosentino

Comments and Discussions

 
GeneralMy vote of 5 Pin
Hyland Computer Systems30-Jan-23 6:20
Hyland Computer Systems30-Jan-23 6:20 
GeneralMy vote of 5 Pin
Hyland Computer Systems30-Jan-23 6:20
Hyland Computer Systems30-Jan-23 6:20 
PraiseRe: My vote of 5 Pin
Dev Leader31-Jan-23 19:13
Dev Leader31-Jan-23 19:13 
QuestionHow discover the dll exact name? Pin
Salam Elias26-Jan-23 0:52
Salam Elias26-Jan-23 0:52 
AnswerRe: How discover the dll exact name? Pin
Dev Leader29-Jan-23 17:55
Dev Leader29-Jan-23 17:55 
GeneralGot my 5 Pin
Angelo Cresta25-Jan-23 20:52
professionalAngelo Cresta25-Jan-23 20:52 
GeneralRe: Got my 5 Pin
Dev Leader29-Jan-23 17:51
Dev Leader29-Jan-23 17:51 
Question5 from me Pin
Nick Polyak25-Jan-23 5:56
mvaNick Polyak25-Jan-23 5:56 
AnswerRe: 5 from me Pin
Dev Leader29-Jan-23 17:51
Dev Leader29-Jan-23 17:51 
PraiseOh the possibilities! Pin
Chris Maunder25-Jan-23 3:20
cofounderChris Maunder25-Jan-23 3:20 
This is awesome and opens up a ton of possibilities for CodeProject.AI Server. I'm way too busy to be distracted by this right now, meaning this will probably kill my productivity for the next 2 days.

I am so weak when it comes to shiny things.
cheers
Chris Maunder

GeneralRe: Oh the possibilities! Pin
Sacha Barber25-Jan-23 3:56
Sacha Barber25-Jan-23 3:56 
GeneralRe: Oh the possibilities! Pin
Dev Leader25-Jan-23 4:51
Dev Leader25-Jan-23 4:51 
GeneralRe: Oh the possibilities! Pin
Chris Maunder25-Jan-23 8:33
cofounderChris Maunder25-Jan-23 8:33 
GeneralRe: Oh the possibilities! Pin
Chris Maunder25-Jan-23 8:34
cofounderChris Maunder25-Jan-23 8:34 
GeneralRe: Oh the possibilities! Pin
Sacha Barber26-Jan-23 2:17
Sacha Barber26-Jan-23 2:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.