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.
Top comments (0)