使用subprocess实现Python向C#传递Arduino数据时遇报错求助
解决Python与C#进程间通信及Arduino数据传递问题
错误原因分析
- Python代码报错是因为
subprocess.Popen.communicate()只能调用一次,调用后会关闭子进程的标准输入/输出流,循环中重复调用自然会触发输入发送失败的错误。 - C#代码存在两个问题:构造函数里的死循环会阻塞UI线程,导致界面无响应;
ReadToEnd()会等待输入流关闭才返回,无法实时接收Python传递的数据。
修正后的Python代码
直接通过子进程的stdin写入数据,避免使用communicate(),同时处理串口数据的编码和缓冲区刷新:
import serial from subprocess import Popen, PIPE import time ser = serial.Serial('COM10', 9600, bytesize=8, timeout=1) # 启动C#程序,无需shell=True(减少额外开销) p = Popen(r"C:\Users\User\source\repos\Program\Program\bin\Debug\Program.exe", stdout=PIPE, stdin=PIPE, stderr=PIPE, text=True) # text=True让输入输出用字符串而非bytes try: while True: data = ser.readline().decode('utf-8').strip() # 解码串口数据并去除换行符 if data: # 跳过空数据 p.stdin.write(data + '\n') # 加换行符让C#可以逐行读取 p.stdin.flush() # 强制刷新缓冲区,确保数据立即发送 print(f"发送数据: {data}") time.sleep(0.1) # 避免循环过于频繁占用资源 except KeyboardInterrupt: # 程序终止时清理资源 ser.close() p.stdin.close() p.terminate()
修正后的C#代码
使用后台线程实时读取标准输入,通过Invoke跨线程更新UI控件,避免阻塞界面:
using System; using System.IO; using System.Threading; using System.Windows.Forms; namespace Program { public partial class Form1 : Form { public Form1() { InitializeComponent(); // 启动后台线程读取输入 Thread inputThread = new Thread(ReadInput); inputThread.IsBackground = true; // 后台线程随程序关闭自动终止 inputThread.Start(); } private void ReadInput() { StreamReader reader = new StreamReader(Console.OpenStandardInput()); while (true) { string line = reader.ReadLine(); // 逐行读取,实时响应数据 if (!string.IsNullOrEmpty(line)) { // 跨线程更新Label(UI控件只能在创建它的线程操作) label1.Invoke((MethodInvoker)delegate { label1.Text = line; }); } } } } }
额外注意事项
- 确保Arduino使用
Serial.println()发送数据(默认会添加换行符,适配C#的ReadLine()),且数据为UTF-8编码。 - Python中
serial.Serial的timeout参数可以避免readline()长时间阻塞。 - 如果需要处理C#程序的输出或错误,可以在Python中单独开启线程读取
p.stdout和p.stderr,避免主循环阻塞。
内容的提问来源于stack exchange,提问作者GabrielSofrone
相关产品推荐
相关产品推荐

