WPF应用中C#调用Python预测模型时执行出错求助
你的核心问题是:WPF通过C#调用Python脚本时,模型predict环节报错,但脚本直接在Python环境运行正常,且多种调用方式均无效。以下是针对性的排查步骤和修复方案:
一、先获取完整错误信息
你提供的报错日志仅显示了predict行的回溯,缺少具体错误类型(如ValueError/AttributeError),这是定位问题的关键。先修改C#代码确保捕获完整错误输出:
修改后的C#调用代码
private void Button_Click(object sender, RoutedEventArgs e) { string scriptPath = @"E:\TrainedModels\inversetest.py"; var result = RunPythonScript(scriptPath); // 这里可以打印result到日志或界面,查看完整输出 } public static string RunPythonScript(string scriptPath) { string scriptDir = Path.GetDirectoryName(scriptPath); ProcessStartInfo startInfo = new ProcessStartInfo { FileName = @"C:\Users\PC 4\AppData\Local\Programs\Python\Python312\python.exe", Arguments = $"\"{scriptPath}\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, WorkingDirectory = scriptDir // 关键:设置工作目录为脚本所在文件夹 }; using (Process process = new Process { StartInfo = startInfo }) { process.Start(); // 先读错误输出,避免缓冲区溢出导致日志截断 string error = process.StandardError.ReadToEnd(); string output = process.StandardOutput.ReadToEnd(); process.WaitForExit(); return string.IsNullOrEmpty(error) ? output : $"Error: {error}"; } }
二、排查核心问题
1. 工作目录不匹配(最常见原因)
直接运行Python脚本时,工作目录是脚本所在的E:\TrainedModels,但C#默认工作目录是WPF程序的输出目录(如bin\Debug),导致脚本中用相对路径读取的invtest.csv、.sav模型文件找不到,最终在predict环节因为数据/模型加载失败报错。
修复: 上面的C#代码已经开启了WorkingDirectory = scriptDir,强制将Python进程的工作目录设置为脚本所在文件夹,确保相对路径有效。
2. Python环境不一致
你直接运行脚本的Python环境(比如conda虚拟环境)和C#调用的Python312可能依赖库版本不兼容:
- 模型是用旧版本的
scikit-learn/tensorflow保存的,新版本库加载后predict方法参数不兼容 pandas/numpy版本差异导致数据格式处理不一致
排查方法: 在Python脚本开头加入环境打印代码,对比直接运行和C#调用的输出:
import sys import pandas as pd import numpy as np import sklearn # 如果是sklearn模型 print(f"Python版本: {sys.version}") print(f"Pandas版本: {pd.__version__}") print(f"Numpy版本: {np.__version__}") print(f"Sklearn版本: {sklearn.__version__}")
如果版本不一致,给Python312安装和原环境相同版本的依赖库(如pip install scikit-learn==x.x.x)。
3. 数据/模型加载失败
在Python脚本中加入调试代码,确认数据和模型是否成功加载:
# 检查CSV读取 try: Temp_data = pd.read_csv("invtest.csv") print(f"CSV加载成功,数据形状: {Temp_data.shape}") except Exception as e: print(f"CSV加载失败: {str(e)}") exit(1) # 检查模型加载 try: valve_model_Down = pickle.load(open('inverse_Quant_Down.sav','rb')) print(f"Down模型加载成功: {type(valve_model_Down)}") except Exception as e: print(f"Down模型加载失败: {str(e)}") exit(1)
如果输出显示文件找不到,说明工作目录仍有问题;如果模型加载报错,可能是模型文件损坏或版本不兼容。
三、完整调试版Python脚本
将以下代码替换原脚本,运行后通过C#获取输出,即可明确具体错误:
import pandas as pd import numpy as np import pickle import sys import traceback # 打印环境信息 print(f"Python版本: {sys.version}") print(f"Pandas版本: {pd.__version__}") print(f"Numpy版本: {np.__version__}") # 读取数据 try: Temp_data = pd.read_csv("invtest.csv") print(f"CSV数据形状: {Temp_data.shape}") except Exception as e: print(f"CSV加载错误: {str(e)}") traceback.print_exc() sys.exit(1) x = Temp_data[['thickness','Percu1','Percu2','Percu3','Percu4','Percu5','Percu6','Percu7','Percu8','Percu9' ,'Percu10','Percu11','Percu12','Percu13','Percu14','Percu15','Percu16','Percu17' ,'Percu18','Percu19']] print(f"特征数据形状: {x.shape}") X = x / 95 print(f"归一化后特征形状: {X.shape}") # 加载模型 try: valve_model_Down = pickle.load(open('inverse_Quant_Down.sav','rb')) print(f"Down模型加载成功") valve_model_Middle = pickle.load(open('inverse_Quant_Mid.sav','rb')) print(f"Middle模型加载成功") valve_model_Up = pickle.load(open('inverse_Quant_Up.sav','rb')) print(f"Up模型加载成功") except Exception as e: print(f"模型加载错误: {str(e)}") traceback.print_exc() sys.exit(1) # 预测 try: pre_Down = valve_model_Down.predict(X) print(f"Down预测结果形状: {pre_Down.shape}") pre_Middle = valve_model_Middle.predict(X) print(f"Middle预测结果形状: {pre_Middle.shape}") pre_Up = valve_model_Up.predict(X) print(f"Up预测结果形状: {pre_Up.shape}") except Exception as e: print(f"预测错误: {str(e)}") traceback.print_exc()
内容的提问来源于stack exchange,提问作者soheila

