【问题标题】:Communication between Python and C#Python和C#之间的通信
【发布时间】:2017-08-13 20:12:09
【问题描述】:

我有一个运行机器学习算法的 Python 后端。我想为 Excel 插件 (C#) 和网站使用相同的后端。我希望两个接口都将我的训练数据(数组中的数千行数字)发送到同一个 Python 应用程序,并以另一个数组的形式检索结果,最多可达几千行。

网站将从 SQL 数据库中获取数据并将该数据发送到 Python,而 Excel 插件将获取当前工作表中的数据并将该数据发送到 Python。在继续处理数据之前,我需要能够在 Python 中创建 numpy 数组。请注意,该网站将在 Python 应用程序所在的同一台机器上运行。我还没有决定使用什么来编写网站代码,但我倾向于使用 Node.js。

我做了一些研究,发现了一些选择:

1- Named pipes
2- Sockets
3- RPC server such as gRPC or XML-RPC.
4- Writing the data to a file and reading it back in Python
5- Web Service

注意:我需要 Python“服务器”是有状态的,并在调用之间保持会话运行。所以我需要有一个守护进程运行,等待调用。

您的专家会推荐哪一个?为什么?我需要灵活处理多个参数以及大量数字。使用 IronPython 不是一个选项,因为我在 Python 上运行 Keras,它显然不支持 IronPython。

【问题讨论】:

    标签: c# python .net rpc python.net


    【解决方案1】:

    ironpython 会让你的生活变得轻松吗?不要解决它。使用它。

    尝试在您的 ironpython 实例和您的 python 实例之间建立一个 api。对其进行测试并解决任何意外错误。使用重构时重试或(最好在文件夹中加时间戳)日志以防出错(考虑到 Ironpython 是 python 2.7 可能会发生)。最好使用专用(或您的一部分)服务器来使用您的 python 和 numpy 将其传输回您的 c# 服务器。

    重构并享受额外的竞争力

    【讨论】:

      【解决方案2】:

      我最近遇到了同样的问题。 我使用命名管道将数据从 python 传输到我的 c# 服务器,希望对您有所帮助。

      Python:

      import win32pipe, win32file
      
      class PipeServer():
          def __init__(self, pipeName):
              self.pipe = win32pipe.CreateNamedPipe(
              r'\\.\pipe\\'+pipeName,
              win32pipe.PIPE_ACCESS_OUTBOUND,
              win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
              1, 65536, 65536,
              0,
              None)
          
          #Carefull, this blocks until a connection is established
          def connect(self):
              win32pipe.ConnectNamedPipe(self.pipe, None)
          
          #Message without tailing '\n'
          def write(self, message):
              win32file.WriteFile(self.pipe, message.encode()+b'\n')
      
          def close(self):
              win32file.CloseHandle(self.pipe)
      
      
      t = PipeServer("CSServer")
      t.connect()
      t.write("Hello from Python :)")
      t.write("Closing now...")
      t.close()
      

      要使此代码正常工作,您需要安装 pywin32(最好的选择来自二进制文件):https://github.com/mhammond/pywin32

      C#-服务器:

      using System;
      using System.IO;
      using System.IO.Pipes;
      
      class PipeClient
      {
          static void Main(string[] args)
          {
              using (NamedPipeClientStream pipeClient =
                  new NamedPipeClientStream(".", "CSServer", PipeDirection.In))
              {
      
                  // Connect to the pipe or wait until the pipe is available.
                  Console.Write("Attempting to connect to pipe...");
                  pipeClient.Connect();
      
                  Console.WriteLine("Connected to pipe.");
                  Console.WriteLine("There are currently {0} pipe server instances open.",
                     pipeClient.NumberOfServerInstances);
                  using (StreamReader sr = new StreamReader(pipeClient))
                  {
                      // Display the read text to the console
                      string temp;
                      while ((temp = sr.ReadLine()) != null)
                      {
                          Console.WriteLine("Received from server: {0}", temp);
                      }
                  }
              }
              Console.Write("Press Enter to continue...");
              Console.ReadLine();
          }
      }
      

      【讨论】:

      • 管道名称最接近NamedPipeClientStream和win32Pipe.CreateNamedPipe
      【解决方案3】:

      让我以示例代码的形式为您提供一个简洁快捷的食谱。

      基本上有两种方法可以将 python 绑定到 C#(或 C# winform 应用程序或 gui 或类似的东西)的后端。

      方法1:铁蟒。在这种方法中,您可以在名为 IronPython 的 Visual Studio 中安装一个 .net 包。我不喜欢这样,因为假设您的机器学习模型使用 keras 或许多其他库。让您准备好安装并在 IronPython 中工作将是另一个任务。而且最重要的是,它不如你常见的虚拟 env 或 conda 环境。

      方法 2:(好的方法):在您的 C# 中创建一个自定义进程,该进程从您的 GUI 中获取参数,知道脚本的路径和您的 python 环境。使用所有这些东西,它会完全按照您在终端中调用它的方式调用您的 python 代码并将参数传递给它。

      现在是美味的示例代码(我使用了这个简单的技巧,它总是有助于使我的黑屏 python 东西在 C# 应用程序的封面上看起来不错)。

      Python部分

      import sys
      a = sys.argv[1]
      b = sys.argv[2] 
      print("The Sum = ", float(a)+float(b))
      

      C#部分 因此,这是您需要在应用程序中的 sum 按钮的单击事件上调用的 python 进程/函数

      static void PythonProcess()
              {
                  //1) Create Process Info
                  var psi = new ProcessStartInfo();
                  
                  //Conda Env Path
                  psi.FileName = @"C:\Users\jd\.conda\pkgs\py\python.exe";
      
                  //2) Provide Script and the Arguments
                  var script = @"C:\Users\jd\Desktop\script.py";
                  var a = "15";
                  var b = "18";
      
                  psi.Arguments = $"\"{script}\" \"{a}\" \"{b}\"";
      
                  //3) Process Configuration
                  psi.UseShellExecute = false; 
                  psi.CreateNoWindow = true;
                  psi.RedirectStandardOutput = true;
                  psi.RedirectStandardError = true;
      
                  //4) Execute Process and get Output.
                  var errors = "";
                  var results = "";
      
                  using(var process = Process.Start(psi))
                  {
                      errors = process.StandardError.ReadToEnd();
                      results = process.StandardOutput.ReadToEnd();
                  }
      
                  //5) Display Output
                  Console.WriteLine("ERRORS: ");
                  Console.WriteLine(errors);
                  Console.WriteLine();
                  Console.WriteLine("RESULTS: ");
                  Console.WriteLine(results);
              }
      

      【讨论】:

        【解决方案4】:

        我遇到了同样的问题,似乎最终得到了命名管道。 Here 是一个很好的例子,说明如何将其设置为与 C# => Python 对话,假设 C# 是服务器。 它可以使用相同的方式进行回话,也可以直接通过 CLR 调用 Python.net,如 here 所示。我使用后者。

        【讨论】:

          【解决方案5】:

          通过Pyrolite 从 C# 调用 Python 很容易,您的 Python 代码作为Pyro4 服务器运行。它应该足够快来处理“大型数字数组”,但是您没有指定任何性能限制。

          【讨论】:

            【解决方案6】:

            您可以使用Python for .NET (Python.NET)。它可能需要对您的代码进行一些更改,但是一旦一切正常,它应该可以很好地工作。

            Python.NET 允许 CPython 和 CLR 之间进行双向通信。

            【讨论】:

            • 谢谢!我想如果 Keras(我正在使用的机器学习框架)不支持 IronPython,那么适用于 .NET 的 Python 也不支持。您似乎也在做一些神经网络的工作,您是否曾经尝试过使用 Keras/Tensorflow 的 Python for .NET?似乎最新版本适用于 Python 2.7。
            • @VincentLavoie 不,我没有!我实际上是在使用 Processing 用 Ja​​va 编写整个程序。我有点像非 C 语言的菜鸟。如果这不起作用,则可以尝试 IPC 连接。我推荐this post 来帮助你开始使用这些。虽然我个人对它们了解不多,但您可能需要进行一些研究。
            • 在阅读了 Python for .NET 之后,似乎人们在 Python 中使用 CLR .NET 对象,这不是我现在需要的。我需要能够从 C# 调用 Python 脚本并将数组和其他值传递给 Python 脚本。也许我不明白它的工作方式?文档不是很丰富,开发似乎很久以前就停止了。
            • 查看我在上一篇文章中告诉您的那些 IPC 连接。它们似乎是您所需要的。链接的帖子几乎询问了您的确切问题,并得到了比我更好的答案。
            • 您正在提供 5 年前的 Python.NET 项目链接。 Python.NET 允许双向互操作。积极开发在github.com/pythonnet/pythonnet
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-04-01
            • 2011-08-23
            • 2020-12-10
            相关资源
            最近更新 更多