Vision Master的C#脚本与opencv联合编程
需要在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)