我有一个串行设备,正在尝试从中读取输入。我向它发送了一个字符串 "ID\r",然后它返回 "ID XX\r"(其中 \r 是 ASCII 回车,十六进制为 0x0d)。
由于串行.readline 上的 eol 选项不再受支持,我正在使用 TextIOWrapper 从串行端口读取并一次返回一行。
我的问题是,它不是在看到回车符后立即返回我的字符串,而是等待我打开串行端口时设置的两倍超时时间。我希望它在读取完整行后立即返回字符串,因为我可能需要将数百个这些命令发送到设备,并且不想每次都等待超时时间。如果将超时时间设置为 0,则根本没有输出(可能是因为我的脚本在设备有机会输出任何内容之前就停止等待),而如果将超时时间设置为 None,则脚本将永远阻塞。
这是一个简单的测试脚本:
import serial
import io
import time
ser = serial.Serial("/dev/ttyUSB0", baudrate=9600,
bytesize=8, parity='N', stopbits=1,
xonxoff=0, rtscts=1, timeout=5)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser),
newline=None)
sio.write(unicode("ID\r"))
sio.flush()
print "reading..."
x = sio.readline()
print len(x)
print x
脚本总是在显示“reading”和打印从串口读取的“ID XX”字符串之间花费10秒钟。
我确认设备正在输出回车符,因为我已经使用strace监视了读取过程。
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 991704})
read(3, "I", 8192) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999267})
read(3, "D", 8191) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999420})
read(3, " ", 8190) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999321})
read(3, "X", 8189) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999355})
read(3, "X", 8188) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999171})
read(3, "\r", 8187) = 1
select(4, [3], [], [], {5, 0}) = 0 (Timeout)
select(4, [3], [], [], {5, 0}) = 0 (Timeout)
您可以看到有两个select()超时,导致了10秒的延迟,但您也可以清晰地看到回车符被读取。我已经尝试将newline参数设置为'None'和''(应自动允许\r、\n和\r\n),以及'\r',但每次结果都相同。
我还尝试将BufferedRWPair()调用中的buffer_size设置为“1”,以防止缓冲输入,但没有任何区别。
您有什么想法我做错了什么吗?
如果我无法让它正常工作,我的下一步将是使用serial.read()逐个字符读取并进行自己的行缓冲,但我想先尝试使用textiowrapper的“正确”方法。