Mac Sonoma下Python串口读写CSV报OSError: [Errno 6]问题求助
解决方案:Mac Sonoma下Python串口读取+CSV写入的两个问题
一、修复KeyboardInterrupt捕获的语法错误
常见错误是try-except结构缩进错误或except语句写法有误,正确的逻辑是将主循环包裹在try块内,用except捕获中断信号,同时确保中断时释放串口和文件资源。
示例修正代码:
import serial import csv import time # 初始化串口和CSV文件 ser = serial.Serial('/dev/tty.usbmodem14101', 9600, timeout=1) csv_file = open('data.csv', 'a', newline='') writer = csv.writer(csv_file) try: while True: # 读取串口数据 data = ser.readline().decode('utf-8').strip() if data: print(data) # 写入CSV writer.writerow(data.split(',')) # 按需刷新缓冲区,避免数据滞留 csv_file.flush() time.sleep(1) except KeyboardInterrupt: print("\n程序被用户终止") finally: # 无论是否中断,都关闭资源 ser.close() csv_file.close() print("资源已释放")
二、解决OSError: [Errno 6] Device not configured问题
结合你提到的「无文件写入的代码可长期运行」,推测问题出在串口读取与文件IO的阻塞交互,加上Mac Sonoma的USB/串口管理特性导致。以下是针对性解决方案:
1. 优化文件IO操作,减少阻塞
- 保持CSV文件句柄长期打开,避免频繁打开/关闭操作
- 打开文件时设置行缓冲:
open('data.csv', 'a', newline='', buffering=1),平衡性能和数据安全性 - 减少flush()调用频率,比如每10条数据刷新一次,而非每次写入都刷
2. 添加串口异常重连机制
在读取串口时捕获Errno 6错误,尝试重新连接设备,避免程序直接崩溃:
try: data = ser.readline().decode('utf-8').strip() except OSError as e: if e.errno == 6: print("设备连接丢失,尝试重新连接...") ser.close() time.sleep(2) # 等待2秒再重试 try: ser.open() print("重新连接成功") except Exception as re_conn_err: print(f"重新连接失败: {re_conn_err}") break else: raise # 其他OSError抛出处理
3. 调整Mac系统的USB节能设置
- 打开「系统设置」→「电池」(台式机选「电源适配器」)→「选项」
- 取消勾选「如果可能,使端口进入睡眠状态」,防止Mac自动关闭USB端口导致设备断开
4. 升级pyserial库版本
Mac下旧版本pyserial可能存在兼容性问题,执行命令升级:
pip install --upgrade pyserial
5. 用线程分离串口读取与文件写入
将串口读取和CSV写入拆分为独立线程,避免IO阻塞导致串口超时:
import serial import csv import time from threading import Thread, Queue data_queue = Queue() def read_serial(): ser = serial.Serial('/dev/tty.usbmodem14101', 9600, timeout=1) try: while True: data = ser.readline().decode('utf-8').strip() if data: data_queue.put(data) time.sleep(0.1) except OSError as e: print(f"串口读取错误: {e}") finally: ser.close() def write_csv(): with open('data.csv', 'a', newline='', buffering=1) as csv_file: writer = csv.writer(csv_file) while True: if not data_queue.empty(): data = data_queue.get() writer.writerow(data.split(',')) time.sleep(0.5) # 启动线程 serial_thread = Thread(target=read_serial, daemon=True) csv_thread = Thread(target=write_csv, daemon=True) serial_thread.start() csv_thread.start() # 主线程等待中断 try: while True: time.sleep(1) except KeyboardInterrupt: print("\n程序终止")
内容的提问来源于stack exchange,提问作者pedwards1
相关产品推荐
相关产品推荐

