商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C#如何调用Python脚本_C#执行py文件并获取返回结果【跨语言】

C#如何调用Python脚本_C#执行py文件并获取返回结果【跨语言】

  发布于2026-07-08 阅读(0)

扫一扫,手机访问

Process 拉起 Python 解释器,是跨语言调用中最稳妥的路径。没什么花哨,就是老老实实启动一个 python.exe 进程,通过标准输入输出管道通信。关键点有几个:python.exe 路径得对,最好指定绝对路径;脚本也建议用绝对路径,免得工作目录搞鬼;别忘了把 UseShellExecute 设为 false,不然重定向 IO 就没戏了;参数拼进 Arguments 字符串,别塞到 FileName 里。另外,加个 -u 参数能强制 Python 无缓冲输出,输入输出统一用 JSON 格式最省心。超时、读 stderr、检查 ExitCode——这三样少一个,线上就可能出幺蛾子。

C#如何调用Python脚本_C#执行py文件并获取返回结果【跨语言】

Process 启动 Python 解释器是最直接的方式

别走弯路——Assembly.LoadFrom 或者 IronPython 那种内嵌解析器的玩法,除非你有特殊理由,否则绝大多数场景下,Process 就是最稳定、兼容性最好、调试最直观的选择。本质就是额外启动一个独立的 python.exe 进程去跑脚本,C# 这边通过标准输入输出管道跟它对话。

几个躲不开的坑:

  • python.exe 得在系统 PATH 里,或者你直接给完整路径(比如 C:\Python39\python.exe
  • 脚本路径用绝对路径最踏实,避免工作目录不一致冒出 FileNotFoundError
  • UseShellExecute = false 必须设,否则 stdin/stdout 重定向无效
  • Python 脚本的参数全放进 Arguments 字符串,别顺手塞进 FileName
var startInfo = new ProcessStartInfo
{
    FileName = "python.exe",
    Arguments = $"\"{scriptPath}\" --input data.json",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    CreateNoWindow = true
};
using var proc = Process.Start(startInfo);
string output = proc.StandardOutput.ReadToEnd();
string error = proc.StandardError.ReadToEnd();
proc.WaitForExit();
if (proc.ExitCode != 0) throw new InvalidOperationException($"Python failed: {error}");

Python 脚本必须显式输出结果,且避免缓冲干扰

C# 读不到返回值?十有八九是 Python 那边没把结果真“吐出来”。Python 默认对 stdout 做行缓冲(遇到换行才刷出),子进程模式下可能完全不缓冲或全缓冲,结果 C# 一直 ReadToEnd() 阻塞,要么读到空字符串。

解决办法:

  • 启动 Python 时加 -u 参数强制无缓冲:python.exe -u script.py
  • Python 脚本里手动加 print(..., flush=True)
  • 结果尽量用 JSON 格式输出,方便 C# 解析,别用多行乱序的 print 文本
  • 脚本末尾不要留 input() 交互式语句,否则进程卡死等用户输入

示例 Python 脚本(calc.py):

import json
import sys
# 解析命令行参数(简单起见,只取第一个)
if len(sys.argv) > 1:
    try:
        x = float(sys.argv[1])
        result = {"status": "success", "value": x ** 2}
    except Exception as e:
        result = {"status": "error", "message": str(e)}
else:
    result = {"status": "error", "message": "missing arg"}
print(json.dumps(result), flush=True)

传参和接收结果推荐 JSON,别用空格分隔字符串

用空格或制表符分隔参数,一旦遇到带空格的路径、JSON 字符串或者用户输入,立刻崩。C# 拼接 Arguments 字符串时容易漏转义,Python 端 sys.argv 解析也跟着脆弱。

更健壮的做法:

  • 把所有输入数据序列化成 JSON 字符串,写入临时文件或通过 stdin 传入
  • Python 脚本从 sys.stdin 读取并解析
  • 输出也统一用 JSON,C# 用 System.Text.Json.JsonSerializer.Deserialize() 解析
  • 临时文件路径注意权限和清理(尤其多线程并发时),优先走 stdin/stdout

C# 端发送 JSON 输入示例:

var inputJson = JsonSerializer.Serialize(new { a = 5.5, b = "test" });
startInfo.RedirectStandardInput = true;
using var proc = Process.Start(startInfo);
using var writer = proc.StandardInput;
writer.WriteLine(inputJson); // 注意换行,Python 的 input() 或 sys.stdin.readline() 依赖它
writer.Close();

超时、异常、编码——这三处最容易掉坑

没设超时,Python 脚本死循环或卡住,整个 C# 线程就跟着挂了;中文乱码是因为 Python 默认用系统编码(如 GBK),而 C# 的 Process 默认用 UTF-8;捕获不到异常,错误信息全丢进黑洞。

实操要点:

  • 一定用 WaitForExit(milliseconds) 而不是无参版;超时后主动 Kill()
  • 设置 startInfo.StandardOutputEncoding = Encoding.UTF8StandardErrorEncoding,并确保 Python 脚本也用 UTF-8 输出(print(..., flush=True) 在 UTF-8 环境下默认正常)
  • 错误流(StandardError)必须读,否则进程可能因 stderr 缓冲满而僵死
  • Linux/macOS 下命令是 python3 而非 python,跨平台部署要判断环境

真正上线时,这些不是可选项,是必填项。尤其是 stderr 不读、不设超时、不检查 ExitCode——问题一定在半夜出现。

本文转载于:https://www.php.cn/faq/2420277.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注