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
) 中返回给 cshappython 的
sys.stdout.write + 换行符
-
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(); }
-
python 工具脚本
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys if __name__ == "__main__": print("hello world, arg1: {}".format(sys.argv[1])) # 这个就能输出给 csharp
-
测试 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
-
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()