基于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的输出 } }
问题
- 如何在C#应用中实时捕获Python回调函数的输出?
- 使用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
相关产品推荐
相关产品推荐

