Gaurav Gahlot
Posted on September 15, 2024
Introduction
The interoperability between different programming languages enables developers
to leverage the best features of each language. One such powerful combination
is using Python and C# together.
I'm not a C# expert. This blogpost is purely based on my learning while I was
trying to run a Python script from a C# application.
Prerequisites
-
Python Installation: Ensure Python is installed on your machine and that
the Python executable is accessible via the system's
PATH
. You can download Python from the official Python website. - C# Development Environment: You'll need an environment for writing and running C# code. Visual Studio is a popular choice, but you can use any editor or IDE of your choice.
A Python Script
In order to keep it simple, we will be using the following Python script:
def Greet(name):
return f"Hello, {name}!"
Save the file as greeter.py
to follow along.
Before running a Python script from C#, you would typically compile it into a
.pyc
file. Here’s how you can compile your Python script:
- Open a terminal or command prompt.
- Run the following command:
python3 -m compileall greeter.py
This command will generate a directory named __pycache__
containing the
compiled .pyc
file. In our case:
➜ tree .
.
├── __pycache__
│ └── greeter.cpython-312.pyc
└── greeter.py
C# Application
We start off by creating a console
application using the dotnet
CLI:
mkdir netpy && cd netpy
dotnet new console
Next, we add the pythonnet package to the project:
dotnet add package pythonnet
Update the Program.cs
file with the code below to run the compiled (.pyc
)
Python script (greeter.py
):
using Python.Runtime;
// Specify the path to the Python shared library (DLL or .so file)
Runtime.PythonDLL = "/opt/homebrew/Cellar/python@3.12/3.12.4/Frameworks/Python.framework/Versions/3.12/lib/libpython3.12.dylib";
// Initialize the Python engine
PythonEngine.Initialize();
// Use a try-finally block to ensure proper cleanup
try
{
// Acquire the GIL (Global Interpreter Lock)
using (Py.GIL())
{
// Add path to __pycache__ directory
dynamic sys = Py.Import("sys");
sys.path.append("/Users/gaurav.gahlot/workspace/playground/netpy");
// Import the compiled .pyc file
dynamic greeter = Py.Import("greeter");
// Call the Greet function
string result = greeter.Greet("Alice");
Console.WriteLine(result);
}
}
finally
{
// Necessary for proper serialization
AppContext.SetSwitch("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", true);
// Shutdown the Python runtime
PythonEngine.Shutdown();
}
Detailed Explanation
-
Python.Runtime
Initialization:- You must set
Runtime.PythonDLL
property orPYTHONNET_PYDLL
environment variable starting with version 3.0, otherwise you will receiveBadPythonDllException
upon callingInitialize
. - You can read more about the same in their documentation.
- You must set
- Initialize Python Engine:
-
PythonEngine.Initialize()
: This initializes the Python engine, making Python functionalities available within the C# environment.
-
- Using Python with GIL:
-
using (Py.GIL())
: Ensures that the Global Interpreter Lock (GIL) is acquired, which is necessary for thread-safety when interacting with Python objects.
-
- Modifying Python Path:
-
dynamic sys = Py.Import("sys")
andsys.path.append("path")
: Adds the__pycache__
directory to the Python path. This is where the compiled.pyc
file resides.
-
- Import and Execute:
-
dynamic greeter = Py.Import("greeter")
: Imports the compiled Python script. -
string result = greeter.Greet("Alice")
: Calls the Greet function from the imported script and prints the result.
-
- Clean Up:
-
AppContext.SetSwitch("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", true)
: Ensures proper serialization. You can learn more about it in this GitHub issue. -
PythonEngine.Shutdown()
: Properly shuts down the Python engine to clean up resources.
-
Running the Application
- Ensure that you have saved the code changes in
Program.cs
. - Open your terminal and navigate to the directory containing
Program.cs
- Run the application using
dotnet run
:
workspace/playground/netpy via .NET 8.0.401
➜ dotnet run
Hello, Alice!
This will execute the Python script and print the output to the console.
Conclusion
Using Python.NET simplifies the process of integrating Python with C#.
You can leverage the capabilities of Python directly from your C# applications,
making it possible to use Python's extensive libraries and simplicity alongside
C#'s strong performance and robust framework.
I hope this helps you get started with running compiled Python scripts
from C# applications smoothly.
Posted on September 15, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.