最稳方式是用Process启动python.exe绝对路径,禁用UseShellExecute和CreateNoWindow,重定向UTF8编码stdout,用ArgumentList传参,Python脚本需print JSON并flush。

最稳的方式是用 Process 启动 python.exe,别碰 IronPython,也别用 cmd.exe 套壳——前者不支持 NumPy/TensorFlow,后者容易被参数注入、空格路径直接崩。
为什么不能用 IronPython 获取返回值
IronPython 是个纯 .NET 实现的 Python 运行时,它压根不调用系统 Python 解释器。这意味着:
- 所有依赖 C 扩展的包(
numpy、pandas、cv2、torch)全报ModuleNotFoundError - 它不兼容 Python 3.8+ 的语法特性(比如海象运算符
:=) - 项目已多年未更新,GitHub 最后一次 commit 是 2021 年
- 你写
return "ok"它能接住,但一旦脚本里 import 一行import numpy,就当场失败
Process.Start() 必须设的五个关键配置项
直接 new Process 不设置这些,90% 的情况会卡死、乱码、拿不到输出或崩溃:
-
StartInfo.FileName必须是python.exe的**绝对路径**,例如"C:\Python39\python.exe";写"python"依赖 PATH,部署时极易失效 -
StartInfo.UseShellExecute = false:否则无法重定向StandardOutput -
StartInfo.CreateNoWindow = true:避免弹黑窗口,尤其 WinForms/WPF 程序中很突兀 -
StartInfo.RedirectStandardOutput = true:这是读取 Pythonprint()输出的唯一通道 -
StartInfo.StandardOutputEncoding = Encoding.UTF8:中文、emoji、日文路径全靠它保真,Windows 默认是 GBK
传参必须用 ArgumentList,别拼 Arguments
老写法:StartInfo.Arguments = $"script.py {inputPath} {outputPath}" —— 路径含空格、括号、反斜杠时必然出错,还可能被注入恶意命令(比如 inputPath = @"C:data; calc.exe")。
立即学习“Python免费学习笔记(深入)”;
正确做法(.NET 5+):
StartInfo.ArgumentList.Add("script.py");
StartInfo.ArgumentList.Add(inputPath);
StartInfo.ArgumentList.Add(outputPath);
好处:
- 每个参数自动加引号并转义,
"C:my folderile.txt"安然无恙 - 完全规避 shell 注入,参数就是参数,不会被解释成命令
- 比手动拼字符串少写 8 行错误处理逻辑
Python 脚本怎么写才能让 C# 拿到结构化数据
C# 读不到 return 值,只能读 stdout。所以 Python 脚本必须:
- 用
print()输出结果,不是return - 输出前先
sys.stdout.flush()(尤其 Windows 上,不 flush 可能卡住) - 推荐 JSON 格式,C# 用
JsonSerializer.Deserialize<T>()直接转对象 - 别用
logging或stderr输出主体结果,C# 默认不捕获stderr
示例 Python 脚本(calc.py):
import json
import sys
<p>a = float(sys.argv[1])
b = float(sys.argv[2])
result = {"sum": a + b, "product": a * b}
print(json.dumps(result))
sys.stdout.flush()
真正难的不是启动 Python,而是确保两边编码一致、参数安全、输出可解析、超时可控——这些细节漏一个,上线后就会在客户机器上静默失败。


















