unity-工具-csharp与python交互


title: unity-工具-csharp与python交互
categories: Unity3d
tags: [unity, 编辑器, 扩展, python]
date: 2020-03-23 15:35:51
comments: false
mathjax: true
toc: true

很多时候写工具都是使用 python 来写, unity 工具需要调用 python 脚本并获取到执行结果.


非弹窗式

可以从 Python 的 os 的 标准输出 (sys.stdout.write) 中返回给 cshap

python 的 print 其实就是调用 sys.stdout.write + 换行符

  1. csharp 执行 命令行 的方法

        // 可以获取到 py 脚本 print 的值
        public static string ProcCmd(string command, string argument) {
          
          
            ProcessStartInfo psi = new ProcessStartInfo(command);
            psi.Arguments = argument;
            psi.CreateNoWindow = true;
            psi.ErrorDialog = true;
            psi.UseShellExecute = false; 
    
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.RedirectStandardInput = true;
            psi.StandardOutputEncoding = System.Text.UTF8Encoding.UTF8;
            psi.StandardErrorEncoding = System.Text.UTF8Encoding.UTF8;
    
            Process p = Process.Start(psi); 
    
            StringBuilder sb1 = new StringBuilder();
            StreamReader reader = p.StandardOutput;
            while (!reader.EndOfStream) {
          
          
                string line = reader.ReadLine();
                if (!line.StartsWith("---")) {
          
           // 过滤掉自定义的日志, 方便 py 调试
                    sb1.Append(line);
                }
                if (!reader.EndOfStream) {
          
          
                    sb1.Append("\n");
                }
            }
            reader.Close();
    
            StringBuilder sb2 = new StringBuilder();
            StreamReader errorReader = p.StandardError;
            while (!errorReader.EndOfStream) {
          
          
                sb2.Append(errorReader.ReadLine()).Append("\n");
            }
            errorReader.Close();
    
            p.WaitForExit();
            p.Close();
    
            if (sb2.Length > 0) {
          
          
                throw new Exception(string.Format("--- Error, python error, msg:{0}", sb2.ToString()));
            }
            return sb1.ToString();
        }
    
  2. python 工具脚本

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import sys
    
    if __name__ == "__main__":
        print("hello world, arg1: {}".format(sys.argv[1])) # 这个就能输出给 csharp
    
  3. 测试 csharp 执行 python 结果

    string pyPath = Path.Combine(PackConfig.PyToolDir, "tool.py");
    string res = EditorUtils.ProcCmd("python3", string.Format("{0} {1}", pyPath, "getProjBranch"));
    Debug.LogFormat("--- py res: {0}", res);
    


弹窗式

单独一个命令行窗口, 标准输出不会返回给 csharp

  1. csharp 执行 命令行 的方法

        // 弹窗执行 py
        public static void ProcCmdOnWin(string command, string argument) {
          
          
            ProcessStartInfo psi = new ProcessStartInfo(command);
            psi.Arguments = argument;
            psi.CreateNoWindow = true;
            psi.ErrorDialog = true;
            psi.UseShellExecute = true; 
            psi.RedirectStandardOutput = false;
            psi.RedirectStandardError = false;
            psi.RedirectStandardInput = false;
            Process p = Process.Start(psi); 
            p.WaitForExit();
            p.Close();
        }
    

数据结构的传递

一般使用 json 作为数据结构的格式传递给 Python, 但是命令不能正常传递 json 字符串 给 Python 获取, 所以得用曲线救国的方式 base64 encode 一下给 py, 然后在 py 在 decode 解出正常的 json

  • csharp

    public static string Base64Encode(string plainText) {
          
          
        var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
        return System.Convert.ToBase64String(plainTextBytes);
    }
    
    public static string Base64Decode(string base64EncodedData) {
          
          
        var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
        return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
    }
    
  • python

    def base64Encode(plainText: str) -> str:
        return base64.encodebytes(plainText.encode()).decode()
    
    def base64Decode(encodedData: str) -> str:
        return base64.decodebytes(encodedData.encode()).decode()
    

猜你喜欢

转载自blog.csdn.net/yangxuan0261/article/details/105051122