7

I want to integrate code python (hierarchical clustering algorithm) with code C#.

(The idea of ​​the project is to divide similar people and put them into classes using the algorithm. We use language c# (asp.net) and want a method to link the algorithm to the code.)

3
  • IronPython is worth considering, assuming your Python code works with it. It then allows you to bundle that Python code directly in your .NET app.
    – David Arno
    Jan 22, 2019 at 12:16
  • 4
    @DavidArno Unlikely. Hierarchical clustering is probably the one from scikit-learn and that lib does not work with IronPython. Imo that'S the problem of IronPython: It works for the language, but does not capture the bazillion of packages. And without them, python looses a lot Jan 22, 2019 at 12:18

2 Answers 2

20

Ok, we have done this. I would advise you to use a microservice architecture: e.g. your code calls a Python Rest Service which computes the data and returns the result. Or if the operation is long (which clustering is most of the time) use a message queue as broker between the two services.

You can directly call python code from C# using the library http://pythonnet.github.io/. When it works, it works amazingly well. If not, you are in a world of hurt - most especially it sometimes fails to load (deterministig at least, but fun to diagnose). Furthermore, due to python GIL, you are restricted to one Python process. Also, marshalling data between Python and C# is nontrivial and leads to interesting debugging sessions, e.g. trying to poke into the insides of an IENumerable in Python...

Overall, the microservice pattern is easier to build, to reason about,to debug and to build. Only drawback is that you have now 2 or 3 moving parts, which can be a deal breaker.

5
  • 2
    Did you investigate the feasibility of IronPython at the time? Jan 22, 2019 at 12:15
  • 6
    @JohnGo-Soco yes, we did. We used the whole shebang to drive a data science application, so access to numpy, pandas, scipy, scikit-learn etc. was very important. And not all of these libs where supported at the time. I do not think that this has improved, IronPython looks pretty dead to me Jan 22, 2019 at 12:16
  • 1
    I figured that'd be the case. Jan 22, 2019 at 12:18
  • how is your app doing today? I am also doing data app and want to use pandas. What stack are you using now? May 19, 2021 at 20:39
  • 2
    @user1079002 I've lift the firm since but it worked fine. If your app is on a server I would probably use separate services now (like c# service calling python service) but if not the integration is fine. May 20, 2021 at 9:01
3

This article may prove insightful: https://code.msdn.microsoft.com/windowsdesktop/C-and-Python-interprocess-171378ee

It basically details that you write a python script which uses command-line arguments and prints a return value. Your C# code then calls this script with the required arguments and gets the value back from it.

using System; 
using System.IO; 
using System.Diagnostics; 

namespace CallPython 
{ 
    /// <summary> 
    /// Used to show simple C# and Python interprocess communication 
    /// Author      : Ozcan ILIKHAN 
    /// Created     : 02/26/2015 
    /// Last Update : 04/30/2015 
    /// </summary> 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            // full path of python interpreter 
            string python = @"C:\Continuum\Anaconda\python.exe"; 

            // python app to call 
            string myPythonApp = "sum.py"; 

            // dummy parameters to send Python script 
            int x = 2; 
            int y = 5; 

            // Create new process start info 
            ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(python); 

            // make sure we can read the output from stdout 
            myProcessStartInfo.UseShellExecute = false; 
            myProcessStartInfo.RedirectStandardOutput = true; 

            // start python app with 3 arguments  
            // 1st arguments is pointer to itself,  
            // 2nd and 3rd are actual arguments we want to send 
            myProcessStartInfo.Arguments = myPythonApp + " " + x + " " + y; 

            Process myProcess = new Process(); 
            // assign start information to the process 
            myProcess.StartInfo = myProcessStartInfo; 

            Console.WriteLine("Calling Python script with arguments {0} and {1}", x,y); 
            // start the process 
            myProcess.Start(); 

            // Read the standard output of the app we called.  
            // in order to avoid deadlock we will read output first 
            // and then wait for process terminate: 
            StreamReader myStreamReader = myProcess.StandardOutput; 
            string myString = myStreamReader.ReadLine(); 

            /*if you need to read multiple lines, you might use: 
                string myString = myStreamReader.ReadToEnd() */           

            // wait exit signal from the app we called and then close it. 
            myProcess.WaitForExit(); 
            myProcess.Close(); 

            // write the output we got from python app 
            Console.WriteLine("Value received from script: " + myString); 

        } 
    } 
} 
1
  • 1
    You would definitely add the "-u" command line parameter otherwise python buffers it's output, which can be annoying. Also "-m" might be required when you use a module. Also, I dislike this approach. It works, but is not really stable or scalable, especially in a web context. A clustering algorithm takes a lot of memory, so starting a few of them gets funny fast Jan 22, 2019 at 13:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.