如何在.NET Core 3.1中通过PythonNet获取Python脚本输出?
问题:C# Process调用Python脚本无法获取完整输出
尝试通过PythonNet执行Python脚本并获取输出,先使用Process方式调用,但只能拿到部分输出;直接在Python环境运行脚本则能得到完整结果。
所用Python脚本
import sectionproperties.pre.library.primitive_sections as sections from sectionproperties.analysis.section import Section geometry = sections.circular_section(d=50, n=64) geometry.plot_geometry() geometry.create_mesh(mesh_sizes=[2.5]) section = Section(geometry, time_info=True) section.display_mesh_info() section.plot_mesh() section.calculate_geometric_properties() section.calculate_warping_properties() section.calculate_plastic_properties() section.display_results() (ixx_c, iyy_c, ixy_c) = section.get_ic() j = section.get_j() print("Ixx + Iyy = {0:.3f}".format(ixx_c + iyy_c)) print("J = {0:.3f}".format(j))
Process获取的不完整输出
MULTIPOLYGON (((-2 0.375, -0.5625 0.375, -0.5625 1.8125, 0.5625 1.8125, 0.5625 0.375, 2 0.375, 2 0.5625, 0.75 0.5625, 0.75 2, -0.75 2, -0.75 0.5625, -2 0.5625, -2 0.375)), ((-2 0, 2 0, 2 0.375, -2 0.375, -2 0))) Mesh Statistics: - 2038 nodes - 926 elements - 2 regions +---------------------------- Geometric Analysis -----------------------------+ | | |
直接运行Python脚本的完整输出
MULTIPOLYGON (((-2 0.375, -0.5625 0.375, -0.5625 1.8125, 0.5625 1.8125, 0.5625 0.375, 2 0.375, 2 0.5625, 0.75 0.5625, 0.75 2, -0.75 2, -0.75 0.5625, -2 0.5625, -2 0.375)), ((-2 0, 2 0, 2 0.375, -2 0.375, -2 0))) Mesh Statistics: - 2038 nodes - 926 elements - 2 regions ┌──────────────────────────── Geometric Analysis ─────────────────────────────┐ │ │ │ ✅ Geometric analysis --------------------------- 100% [ 2.3120 s ] │ │ complete │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ┌───────────────────────────── Warping Analysis ──────────────────────────────┐ │ │ │ ✅ Warping analysis -------------------------- 100% [ 12.2180 s ] │ │ completed │ │ ✅ 2038x2038 stiffness -------------------------- 100% [ 2.7350 s ] │ │ matrix assembled │ │ ✅ Warping function solved -------------------------- 100% [ 0.0310 s ] │ │ (direct) │ │ ✅ Shear function vectors -------------------------- 100% [ 2.7030 s ] │ │ assembled │ │ ✅ Shear functions solved -------------------------- 100% [ 0.0630 s ] │ │ (direct) │ │ ✅ Shear and warping -------------------------- 100% [ 2.1250 s ] │ │ integrals assembled │ │ ✅ Shear deformation -------------------------- 100% [ 2.4840 s ] │ │ coefficients assembled │ │ ✅ Monosymmetry integrals -------------------------- 100% [ 2.0620 s ] │ │ assembled │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ┌───────────────────────────── Plastic Analysis ──────────────────────────────┐ │ │ │ ✅ Plastic analysis --------------------------- 100% [ 0.0940 s ] │ │ complete │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ Section Properties ┌──────────┬───────────────┐ │ Property │ Value │ ├──────────┼───────────────┤ │ A │ 2.789062e+00 │ │ Perim. │ 1.200000e+01 │ │ Qx │ 1.626709e+00 │ │ Qy │ -3.204902e-16 │ │ cx │ -1.149096e-16 │ │ cy │ 5.832458e-01 │ │ Ixx_g │ 1.935211e+00 │ │ Iyy_g │ 3.233734e+00 │ │ Ixy_g │ -3.022756e-16 │ │ Ixx_c │ 9.864400e-01 │ │ Iyy_c │ 3.233734e+00 │ │ Ixy_c │ -1.153510e-16 │ │ Zxx+ │ 6.962676e-01 │ │ Zxx- │ 1.691294e+00 │ │ Zyy+ │ 1.616867e+00 │ │ Zyy- │ 1.616867e+00 │ │ rx │ 5.947113e-01 │ │ ry │ 1.076770e+00 │ │ phi │ -9.000000e+01 │ │ I11_c │ 3.233734e+00 │ │ I22_c │ 9.864400e-01 │ │ Z11+ │ 1.616867e+00 │ │ Z11- │ 1.616867e+00 │ │ Z22+ │ 1.691294e+00 │ │ Z22- │ 6.962676e-01 │ │ r11 │ 1.076770e+00 │ │ r22 │ 5.947113e-01 │ │ J │ 9.878443e-01 │ │ Iw │ 1.160810e-01 │ │ x_se │ 4.822719e-05 │ │ y_se │ 4.674792e-01 │ │ x_st │ 4.822719e-05 │ │ y_st │ 4.674792e-01 │ │ x1_se │ 1.157666e-01 │ │ y2_se │ 4.822719e-05 │ │ A_sx │ 1.648312e+00 │ │ A_sy │ 6.979733e-01 │ │ A_s11 │ 6.979733e-01 │ │ A_s22 │ 1.648312e+00 │ │ betax+ │ -2.746928e-01 │ │ betax- │ 2.746928e-01 │ │ betay+ │ 9.645438e-05 │ │ betay- │ -9.645438e-05 │ │ beta11+ │ 9.645438e-05 │ │ beta11- │ -9.645438e-05 │ │ beta22+ │ 2.746928e-01 │ │ beta22- │ -2.746928e-01 │ │ x_pc │ -1.149096e-16 │ │ y_pc │ 3.486328e-01 │ │ Sxx │ 1.140530e+00 │ │ Syy │ 2.603760e+00 │ │ SF_xx+ │ 1.638062e+00 │ │ SF_xx- │ 6.743533e-01 │ │ SF_yy+ │ 1.610373e+00 │ │ SF_yy- │ 1.610373e+00 │ │ x11_pc │ 2.393564e-16 │ │ y22_pc │ 3.486328e-01 │ │ S11 │ 2.603760e+00 │ │ S22 │ 1.140530e+00 │ │ SF_11+ │ 1.610373e+00 │ │ SF_11- │ 1.610373e+00 │ │ SF_22+ │ 6.743533e-01 │ │ SF_22- │ 1.638062e+00 │ └──────────┴───────────────┘ Ixx + Iyy = 4.220 J = 0.988
使用的C# Process代码
var psi = new ProcessStartInfo(); psi.FileName = @"python.exe"; var script = @"script.py"; psi.Arguments = $"\"{script}\""; psi.UseShellExecute = false; psi.CreateNoWindow = true; psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; psi.LoadUserProfile = true; var errors = ""; var results = ""; using (var process = Process.Start(psi)) { errors = process.StandardError.ReadToEnd(); results = process.StandardOutput.ReadToEnd(); process.WaitForExit(); }
解决方法
原因分析
- 同步读取死锁:当前代码先读取
StandardError再读取StandardOutput,若Python进程向标准错误输出大量内容,会填满缓冲区导致进程阻塞,无法继续向标准输出写入,最终造成死锁,只能拿到部分输出。 - 库输出特性:sectionproperties库的进度信息、结果表格可能部分输出到标准错误流,仅读取标准输出会遗漏这部分内容。
修正后的C#代码
采用异步方式同时读取标准输出和标准错误,避免死锁并合并两个流的内容:
var psi = new ProcessStartInfo(); psi.FileName = @"python.exe"; var script = @"script.py"; psi.Arguments = $"\"{script}\""; psi.UseShellExecute = false; psi.CreateNoWindow = true; psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; psi.LoadUserProfile = true; var outputBuilder = new StringBuilder(); var errorBuilder = new StringBuilder(); using (var process = Process.Start(psi)) { // 异步读取输出和错误流 var outputTask = process.StandardOutput.ReadToEndAsync(); var errorTask = process.StandardError.ReadToEndAsync(); // 等待进程退出 process.WaitForExit(); // 获取结果 outputBuilder.Append(await outputTask); errorBuilder.Append(await errorTask); } var fullOutput = outputBuilder.ToString() + errorBuilder.ToString(); // 处理完整输出
额外优化:修改Python脚本输出
若仅需关键结果,可修改Python脚本,将所需内容统一输出到标准输出,或写入临时文件后读取:
import sectionproperties.pre.library.primitive_sections as sections from sectionproperties.analysis.section import Section import matplotlib import json # 关闭绘图避免阻塞(不需要可视化时) matplotlib.use('Agg') geometry = sections.circular_section(d=50, n=64) geometry.create_mesh(mesh_sizes=[2.5]) section = Section(geometry, time_info=True) section.calculate_geometric_properties() section.calculate_warping_properties() section.calculate_plastic_properties() # 提取关键属性 (ixx_c, iyy_c, ixy_c) = section.get_ic() j = section.get_j() # 输出关键结果 print("Ixx + Iyy = {0:.3f}".format(ixx_c + iyy_c)) print("J = {0:.3f}".format(j)) # 将完整属性转为JSON输出,方便C#解析 props = { "A": section.get_area(), "Ixx_c": ixx_c, "Iyy_c": iyy_c, "J": j, "cx": section.get_cx(), "cy": section.get_cy() } print(json.dumps(props))
内容的提问来源于stack exchange,提问作者Mariam Sultan
相关产品推荐
相关产品推荐

