You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Python.Runtime在C#控制台应用捕获Python回调字符串数据

C# .NET控制台集成Python音频转写的实时回调捕获问题

我正在开发一个C# .NET控制台应用,需要集成Python功能实现音频转写。Python脚本通过回调函数print_partial_transcript输出转写过程中的部分转录内容,目前已能通过Python.Runtime成功调用该脚本,但无法直接在C#应用中实时捕获该回调输出的字符串数据。

相关代码

Python代码(transcription.py)

def print_partial_transcript(msg):
    print(f"[partial] {msg['metadata']['transcript']}")

C#代码片段

using Python.Runtime;

public void StartTranscription()
{
   Runtime.PythonDLL = @"C:\Users\python311.dll";
   PythonEngine.Initialize();

    using (Py.GIL())
    {
        dynamic pyScript = Py.Import("transcription");
        // 此处需捕获print_partial_transcript的输出
    }
}

问题

  1. 如何在C#应用中实时捕获Python回调函数的输出?
  2. 使用Python.Runtime在C#应用中集成Python回调功能,是否有更优方案?

解决方案

问题1:实时捕获Python回调输出

提供两种可靠的实时捕获方案:

方案1:重定向Python标准输出流

利用Python的sys.stdout重定向,将print输出的内容导向自定义流,再传递给C#处理:

修改后的Python代码

import sys

class CustomStdout:
    def write(self, text):
        if text.strip():
            # 调用C#注册的回调方法
            if hasattr(sys, 'csharp_callback'):
                sys.csharp_callback(text.strip())

sys.stdout = CustomStdout()

def print_partial_transcript(msg):
    print(f"[partial] {msg['metadata']['transcript']}")

对应C#代码

using Python.Runtime;
using System;

public void StartTranscription()
{
   Runtime.PythonDLL = @"C:\Users\python311.dll";
   PythonEngine.Initialize();

    using (Py.GIL())
    {
        dynamic sys = Py.Import("sys");
        // 定义C#回调逻辑
        Action<string> csharpCallback = (text) =>
        {
            Console.WriteLine($"C#捕获到部分转录: {text}");
        };
        // 将C#委托绑定到Python的sys模块
        sys.csharp_callback = csharpCallback.ToPython();

        dynamic pyScript = Py.Import("transcription");
        // 调用启动转写的方法(需自行实现)
        pyScript.start_transcription();
    }
}

方案2:直接传入C#委托作为Python回调

跳过print输出环节,让Python直接调用C#的回调方法传递原始数据:

修改后的Python代码

def start_transcription(partial_callback):
    # 模拟音频转写循环(实际替换为真实处理逻辑)
    while True:
        partial_data = {"metadata": {"transcript": "正在识别的内容..."}}
        partial_callback(partial_data)
        import time
        time.sleep(1)

对应C#代码

using Python.Runtime;
using System;

public void StartTranscription()
{
   Runtime.PythonDLL = @"C:\Users\python311.dll";
   PythonEngine.Initialize();

    using (Py.GIL())
    {
        dynamic pyScript = Py.Import("transcription");
        // 定义C#回调,直接解析Python传递的字典数据
        Action<PyObject> partialCallback = (pyMsg) =>
        {
            dynamic msg = pyMsg;
            string transcript = msg.metadata.transcript;
            Console.WriteLine($"实时转录内容: {transcript}");
        };
        // 将C#委托转为Python可调用对象并传入
        pyScript.start_transcription(partialCallback.ToPython());
    }
}

问题2:Python.Runtime集成回调的更优方案

优先选择直接传入C#委托作为Python回调的方案,优势如下:

  • 避免标准输出重定向的编码问题和额外开销
  • 直接获取原始Python数据结构(如字典),无需解析打印字符串,减少数据转换错误
  • 代码逻辑更清晰,Python专注业务逻辑,C#负责结果处理

额外优化建议:

  • 回调中若有耗时操作,使用Py.ReleaseGil()释放GIL,避免阻塞Python线程
  • 在C#回调中添加异常捕获,防止数据传递异常导致应用崩溃
  • 应用退出时调用PythonEngine.Shutdown(),确保Python资源被正确释放

内容的提问来源于stack exchange,提问作者Source

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:22:32