运行EXE版传感器读取程序时出现延迟卡顿的解决方法
解决EXE打包后传感器数据GUI输出延迟卡顿问题
核心问题分析
打包成EXE后出现的批量输出延迟,主要是子进程标准输出缓冲导致的——控制台运行时Python默认是行缓冲,但打包成EXE后可能切换为块缓冲,导致输出攒够一定量才一次性吐出;另外频繁的GUI控件更新也会加重主线程负担,进一步影响流畅度。
具体解决方案
1. 禁用子进程输出缓冲
这是解决批量输出问题最直接的手段,有两种实现方式:
- 方式一:修改IES2V2.py的输出逻辑,给所有
print语句添加flush=True参数,强制实时刷新输出:
print('\n---- Reading Data ----', flush=True) print("Live update of sensor data PROCESS_ADDR will begin. Press the 'Enter' key to stop the updates.", flush=True) time.sleep(5) prev_process_addr = ies2.get_value(122) while True: print(f'Update of PROCESS_ADDR : {ies2.get_value(122)}', flush=True) new_process_addr = ies2.get_value(122) if new_process_addr != prev_process_addr: print(f"PROCESS_ADDR value changed! {prev_process_addr} to {new_process_addr}", flush=True) prev_process_addr = new_process_addr if keyboard.is_pressed('enter'): print("\nKey pressed! Stopping the sensor updates.", flush=True) break
- 方式二:启动子进程时配置无缓冲,在
subprocess.Popen中添加bufsize=0参数:
with subprocess.Popen(["python", "IES2V2.py", "--port", self._port, "--current", selected_current.name, "--output", selected_output.name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0) as process:
2. 优化GUI更新逻辑
当前每行插入后都调用text_box.update()会频繁触发GUI重绘,加重主线程负担,可做如下优化:
def retrieve_data_thread(self): selected_current = LoadCurrent[currentgrp.get()] selected_output = OutputType[outputgrp.get()] print(f"Selected Current: {selected_current}, Selected Output: {selected_output}") line_count = 0 with subprocess.Popen(["python", "IES2V2.py", "--port", self._port, "--current", selected_current.name, "--output", selected_output.name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0) as process: for line in process.stdout: line = line.decode() text_box.insert(END, line) line_count += 1 # 每5行更新一次GUI,减少刷新频率 if line_count % 5 == 0: text_box.see(END) text_box.update_idletasks() # 用轻量的update_idletasks替代update,仅处理待完成的GUI事件 process.poll()
3. 检查打包配置(以PyInstaller为例)
如果用PyInstaller打包,需注意:
- 确保子进程依赖文件完整,之前的缺失文件问题可能导致子进程运行异常,间接影响输出节奏,可先用
--onedir参数生成单目录版本,确认所有依赖文件都被正确打包; - 若使用
--windowed参数打包GUI程序,可尝试添加--disable-windowed-traceback避免异常输出干扰。
4. 进阶替代方案:结构化数据传递
如果上述方法仍有问题,可以让IES2V2.py通过管道发送JSON结构化数据,减少解析和缓冲问题:
- IES2V2.py中输出结构化数据:
import sys, json # 替代print语句 sys.stdout.write(json.dumps({"type": "info", "content": "---- Reading Data ----"}) + '\n') sys.stdout.flush() # 传感器更新时同理 sensor_val = ies2.get_value(122) sys.stdout.write(json.dumps({"type": "update", "addr": sensor_val}) + '\n') sys.stdout.flush()
- 主进程中解析数据后更新GUI:
import json # ... for line in process.stdout: line = line.decode().strip() if not line: continue data = json.loads(line) if data["type"] == "info": text_box.insert(END, data["content"] + '\n') elif data["type"] == "update": text_box.insert(END, f'Update of PROCESS_ADDR : {data["addr"]}\n') # 按需更新GUI text_box.see(END) text_box.update_idletasks()
验证步骤
- 先在PyCharm中测试修改后的IES2V2.py,确认输出流畅;
- 重新打包EXE,测试输出是否实时;
- 若仍有延迟,逐步应用GUI优化和打包配置调整。
内容的提问来源于stack exchange,提问作者user23301468
相关产品推荐
相关产品推荐

