Calling Python from C#: an introduction to PythonNET

somegenericdev
4 min readSep 29, 2021

--

Recently, I had to dig into PythonNET since I had to find a way to call Python scripts from my C# projects at work. Surprisingly enough, I found very little material online on the subject and most of it was contradictory or rather confusing. PythonNET’s official documentation wasn’t particularly helpful either, so I decided to write this guide for those who will find themselves in the same situation as me in the future.

Compile PythonNET’s dll

First thing we’re going to do is compiling PythonNET’s dll. Download PythonNET’s source code from Github, open it with Visual Studio and compile the project called “Python.Runtime”. If the compilation is successful, it will generate a .dll file in pythonnet-master\pythonnet\runtime\Python.Runtime.dll

Just click on compile and wait for it to finish. That’s it!

Python prerequisites

At the moment when this guide was written (September 2021), PythonNET supports only Python 3.6–3.8. Python’s last available release is the 3.9.7. Check if you have a newer version of Python installed on your machine and, if that’s the case, be absolutely sure to uninstall it to avoid any problems. You can then download Python 3.8 from here.

If you have a version like “3.8.10” or something like that it should be fine, PythonNET doesn’t seem to mind until you reach 3.9 and up from my personal experience.
You will also need to install PythonNET’s module by launching pip install pythonnet from the CMD.

Create a test application

Let’s create a console application called “TestProject” and add a reference to PythonNET’s dll (Python.Runtime.dll) in it.

Hello world

Let’s create a class named “PythonInterop”. We are going to create an Initialize method, where we’re going to set Python’s dll as an environment variable (be sure to replace my path with yours) and Initialize PythonNET’s engine. You can find Python’s dll in Python’s installation path. By default, it should be C:\Users\YourUserNameHere\AppData\Local\Programs\Python\Python38\python38.dll. for Python 3.8.0.

NOTE: If you’re planning on running PythonNET on Linux, you want to look for Python’s .so file instead! It can be quite hard to find since it isn’t always found in the same directory. You can try to run this script to get its location:

wget https://gist.githubusercontent.com/tkf/d980eee120611604c0b9b5fef5b8dae6/raw/9f074cd233f83180676b4421212ed33c257968af/find_libpython.py
/usr/bin/python3 find_libpython.py --list-all

We are also going to create a method to run our Python code with PythonNET.

Now let’s go in Program.cs and launch our hello world.

Use C# classes in Python

To import C# classes, variables and methods into Python we need to import a module called clr.
Let’s create a class named “MyClass” with a string property named “MyVar”.

In our Program.cs file, let’s run

If everything went well, we should see our variable printed in the Console.

Be careful when you type the string containing Python’s code. Do this
and NOT this! Python uses indentation to define scope, so including unnecessary tabs and spaces in your string will most likely lead to errors!

In this way we can import any class, including C#’s System classes, and use their methods too.

It works!

Use C# types from Python

In the same way, PythonNET lets us se C#’s types from Python aswell.

Import variables with PythonNET’s methods

An alternative way to import C# variables into Python is using PythonNET’s methods.

Let’s create an overload of the RunPythonCode method in our PythonInterop class

parameter is the variable that we want to inject into Python, parameterName is the name that we want the variable to have inside of Python (usually, the same as C#).

Let’s create a Person class and test our method.

Return values from Python to C#

Let’s suppose now that we want to return a variable from Python into C# to perform some other operations on it.
To do so, let’s go back into our PythonInterop class and create a method.

returnedVariableName is the name of the Python variable that we want to get returned in C#.
Let’s try to edit the Age property’s value, to assign it to a variable and to return it to C#.

Import from external projects

You can also easily import from external libraries using the clr module. Let’s create a class library called “MyLibrary” in our solution and let’s reference it from our main Console Application method.
After that, let’s add a class called “LibClass” in our library.

Now, let’s just try to print our string from Python.

Final notes

This was meant as a short introduction to PythonNET for absolute beginners, since it was so difficult for me to find material like this online.
From now on you will probably have a decent toolset that you can use to research and pursue your goals with PythonNET on your own. Good luck!
I’m going to leave the full source of the PythonInterop class below.

--

--

somegenericdev

I like experimenting with Blazor and .NET and posting about my findings.