需要在VM的C#腳本設置string類型Out變量和float類型OutF變量,python的輸出信息會在Out變量顯示
using System;
using System.IO;
using Script.Methods;
using System.Diagnostics;
using System.Net.Sockets;
using System.Text;
using System.Threading;public partial class UserScript : ScriptMethods, IProcessMethods
{private PythonTcpRunner _pythonRunner;private Process _pythonProcess; // 保持進程引用public new int nErrorCode;private string pythonEdio=@"C:\T\python.exe";private string python= @"C:\T\清晰度評估.py";/// <summary>/// 初始化:啟動Python進程并建立TCP連接/// </summary>public void Init(){// 初始化TCP運行器(使用本地8888端口)_pythonRunner = new PythonTcpRunner(pythonEdio,python,"127.0.0.1",8888);// 啟動Python進程并等待TCP服務就緒string errorMsg;if (!_pythonRunner.StartProcess(out _pythonProcess, out errorMsg)){nErrorCode = -1;Out = "初始化Python進程失敗: " + errorMsg;}}/// <summary>/// 執行流程:通過TCP發送請求/// </summary>public bool Process(){try{// 檢查進程狀態if (_pythonProcess == null || _pythonProcess.HasExited){string errorMsg;if (!_pythonRunner.RestartProcess(out _pythonProcess, out errorMsg)){nErrorCode = -1;Out = "重啟Python進程失敗: " + errorMsg;return false;}}// 通過TCP發送執行請求string errorMessage;string outputMessage;bool success = _pythonRunner.SendRequest("EXECUTE", out errorMessage, out outputMessage, 5000);Out = string.IsNullOrWhiteSpace(outputMessage) ? errorMessage : outputMessage;// 嘗試將輸出轉換為float并賦值給OutFfloat result;if (!float.TryParse(outputMessage, out result)){// 如果轉換失敗,設置為NaN或其他默認值OutF = float.NaN;}else{OutF = result;}if (!success){nErrorCode = -2;return false;}nErrorCode = 0;return true;}catch (Exception ex){nErrorCode = -3;Out = string.Format("執行異常: {0}", ex.Message);return false;}}/// <summary>/// 釋放資源:關閉進程和連接,使用override關鍵字重寫基類方法/// </summary>public override void Dispose(){// 發送退出指令(修復輸出參數錯誤,兼容.NET 4.6)if (_pythonRunner != null){string dummyError;string dummyOutput;_pythonRunner.SendRequest("EXIT", out dummyError, out dummyOutput, 1000);}if (_pythonProcess != null && !_pythonProcess.HasExited){try{_pythonProcess.WaitForExit(2000);if (!_pythonProcess.HasExited)_pythonProcess.Kill();}catch { }finally{_pythonProcess.Dispose();_pythonProcess = null;}}// 關閉連接(兼容.NET 4.6)if (_pythonRunner != null){_pythonRunner.Close();}// 調用基類的Dispose方法base.Dispose();}
}/// <summary>
/// 基于TCP的Python運行器
/// </summary>
public class PythonTcpRunner
{private string _pythonPath;private string _scriptPath;private string _ip;private int _port;private TcpClient _client;public PythonTcpRunner(string pythonPath, string scriptPath, string ip, int port){_pythonPath = pythonPath;_scriptPath = scriptPath;_ip = ip;_port = port;}/// <summary>/// 啟動Python進程/// </summary>public bool StartProcess(out Process process, out string errorMessage){errorMessage = string.Empty;process = null;try{var startInfo = new ProcessStartInfo{FileName = _pythonPath,Arguments = string.Format("\"{0}\" {1} {2}", _scriptPath, _ip, _port),UseShellExecute = false,CreateNoWindow = true,WorkingDirectory = Path.GetDirectoryName(_scriptPath)};process = Process.Start(startInfo);if (process == null){errorMessage = "無法啟動Python進程";return false;}// 等待TCP服務啟動(最多等3秒)int retry = 0;while (retry < 30){try{_client = new TcpClient();var result = _client.BeginConnect(_ip, _port, null, null);var success = result.AsyncWaitHandle.WaitOne(100);if (success){_client.EndConnect(result);return true;}}catch { }retry++;Thread.Sleep(100);}errorMessage = "Python TCP服務啟動超時";process.Kill();return false;}catch (Exception ex){errorMessage = ex.Message;return false;}}/// <summary>/// 重啟進程/// </summary>public bool RestartProcess(out Process process, out string errorMessage){Close();return StartProcess(out process, out errorMessage);}/// <summary>/// 發送TCP請求/// </summary>public bool SendRequest(string command, out string errorMessage, out string outputMessage, int timeout){errorMessage = string.Empty;outputMessage = string.Empty;try{if (_client == null || !_client.Connected){errorMessage = "TCP連接已斷開";return false;}var stream = _client.GetStream();stream.ReadTimeout = timeout;stream.WriteTimeout = timeout;// 發送指令(UTF8編碼,以換行符結束)byte[] data = Encoding.UTF8.GetBytes(command + "\n");stream.Write(data, 0, data.Length);// 讀取響應(直到收到結束標記)using (var ms = new MemoryStream()){byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0){ms.Write(buffer, 0, bytesRead);// 檢查是否包含結束標記string temp = Encoding.UTF8.GetString(ms.ToArray());if (temp.Contains("\nEOF\n")){outputMessage = temp.Replace("\nEOF\n", "").Trim();return true;}}}errorMessage = "未收到完整響應";return false;}catch (Exception ex){errorMessage = ex.Message;return false;}}/// <summary>/// 關閉連接/// </summary>public void Close(){try{if (_client != null){_client.Close();}}catch { }_client = null;}
}
import sys
import time
import socket# 簡單的數字運算函數
def simple_calculation(input_num):result = (input_num ** 2) + (input_num * 1.5) - 42time.sleep(0.1)return round(result, 2)# 簡化的TCP服務器
class SimpleServer:def __init__(self, host, port):self.host = hostself.port = portself.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.server_socket.bind((host, port))self.server_socket.listen(1)self.running = Trueself.client_socket = Noneself.test_numbers = [12, 34, 56, 78, 90]def handle_client(self):while self.running and self.client_socket:try:data = self.client_socket.recv(1024).decode('utf-8').strip()if not data:breakif data == "EXECUTE":result = self.process_numbers()self.client_socket.sendall((result + "\nEOF\n").encode('utf-8'))elif data == "EXIT":self.running = Falseself.client_socket.sendall("已退出\nEOF\n".encode('utf-8'))breakelse:self.client_socket.sendall(("未知指令\nEOF\n").encode('utf-8'))except Exception as e:error_msg = f"處理請求出錯: {str(e)}\nEOF\n"self.client_socket.sendall(error_msg.encode('utf-8'))breakdef process_numbers(self):total_start = time.perf_counter()results = []for num in self.test_numbers:try:result = simple_calculation(num)results.append(f"數字 {num} 的計算結果: {result}")except Exception as e:results.append(f"錯誤: {str(e)}")total_elapsed = time.perf_counter() - total_startresults.append(f"\n總處理時間: {total_elapsed:.4f}秒")return "\n".join(results)def start(self):print(f"TCP服務器啟動在 {self.host}:{self.port}")try:self.client_socket, addr = self.server_socket.accept()print(f"客戶端 {addr} 已連接")self.handle_client()finally:self.stop()def stop(self):if self.client_socket:self.client_socket.close()self.server_socket.close()print("服務器已停止")if __name__ == "__main__":if len(sys.argv) != 3:print("用法: python simple_server.py [host] [port]")sys.exit(1)host = sys.argv[1]port = int(sys.argv[2])server = SimpleServer(host, port)try:server.start()except KeyboardInterrupt:server.stop()sys.exit(0)