Linux下pyserial打开/dev/ttyUSB0串口报BrokenPipeError问题咨询
问题根因
pyserial 打开串口设备时,默认会执行完整的标准RS232串口初始化流程,包含RTS、DTR等硬件流控引脚的状态置位操作,会通过fcntl.ioctl向设备发送对应控制指令。
你使用的USB条码扫描枪属于模拟串口(CDC ACM)类设备,多数这类低成本扫描枪仅实现了串口的数据收发通道逻辑,完全没有实现硬件流控相关的指令响应逻辑。你用cat < /dev/ttyUSB0读取时,仅会对设备做普通字符流读取操作,不会触发流控相关的ioctl调用,因此可以正常回显条码;但pyserial初始化阶段发送RTS状态更新的控制指令时,设备无法响应甚至直接断开通信管道,就会抛出BrokenPipeError: [Errno 32] Broken pipe报错。
这个问题和Python版本无关,Python2.7、Python3.5下的pyserial默认初始化逻辑一致,因此会出现相同报错。
解决方案
按优先级尝试以下方案即可:
- 方案1:修改pyserial初始化参数,禁用硬件流控,跳过不必要的引脚置位
初始化串口时显式关闭RTS/CTS、DSR/DTR硬件流控,避免触发不支持的ioctl调用,参考代码:import serial ser = serial.Serial( port='/dev/ttyUSB0', baudrate=9600, # 替换为你的扫描枪实际波特率,绝大多数设备默认值为9600 parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_1, bytesize=serial.EIGHTBITS, timeout=2, rtscts=False, # 关闭RTS/CTS硬件流控 dsrdtr=False # 关闭DSR/DTR硬件流控 ) # 若上述参数配置后仍触发报错,可追加两行手动拉低对应引脚状态 ser.rts = False ser.dtr = False # 测试读取 while True: data = ser.readline() if data: print("扫描得到条码:", data.decode().strip()) - 方案2:直接以普通字符文件方式读取设备
既然通过cat命令可以直接读取设备输出,说明设备本身就是标准的可读取字符流文件,不需要依赖pyserial的串口控制逻辑,可以直接用Python内置的文件操作接口读取,完全绕开pyserial的初始化流程:# 以原始无缓冲只读模式打开设备 with open('/dev/ttyUSB0', 'rb', buffering=0) as dev: while True: line = dev.readline() if line: barcode = line.decode(errors='ignore').strip() print("扫描得到条码:", barcode) - 前置权限检查
执行脚本前先确认当前用户对/dev/ttyUSB0有读写权限,若权限不足可执行以下命令将当前用户加入串口设备对应的用户组,重启终端后生效:sudo usermod -aG dialout $USER
内容的提问来源于stack exchange,提问作者Ferdinando Ceci
相关产品推荐
相关产品推荐

