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)