【问题标题】:Python serial (pySerial) Reading lines with EOL \r instead of \nPython 串行 (pySerial) 用 EOL \r 而不是 \n 读取行
【发布时间】:2017-07-20 13:13:26
【问题描述】:

我正在通过 RS232 电缆与 SR830 锁定放大器通信。读取数据时如下代码:

import serial

def main():
    ser = serial.Serial(
        port='COM6',
        baudrate=19200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS)
    ser.timeout=1
    ser.write("OUTP? 1 \r\n".encode()) #Asks the Lock-in for x-value
    ser.write("++read\r\n".encode())
    x=ser.readline()
    print (x)
if __name__ == '__main__': main()

我得到一个像b'-3.7486e-008\r' 这样的字节字符串。但是,ser.readline() 函数无法将 \r 识别为 EOL。所以每次读取数据都要等待超时,这样会很麻烦,因为我想尽可能快的拿很多分。而且数字的长度变化很大,所以我不能只使用ser.read(12)。我曾尝试使用 io.TextIOWrapper 但我不清楚如何实现它。这是我的尝试:

import serial
import io
def main():
    ser = serial.Serial(
        port='COM6',
        baudrate=19200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS)
    ser.timeout=1
    sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))
    sio.write("OUTP? 1 \r\n") #Asks the Lock-in for x-value
    sio.write("++read\r\n")
    x=sio.readline()
    print (x)
if __name__ == '__main__': main()

这只是打印一个空格。任何帮助将不胜感激,谢谢。

编辑: 这是我在回答后的工作代码,使用循环:

import serial
def main():
    ser = serial.Serial(
        port='COM6',
        baudrate=19200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS)
    ser.timeout=5
    ser.write("OUTP? 1 \r\n".encode()) #Asks the Lock-in for x-value
    ser.write("++read\r\n".encode())
    buffer = ""
    while True:
        oneByte = ser.read(1)
        if oneByte == b"\r":    #method should returns bytes
            print (buffer)
            break
        else:
            buffer += oneByte.decode()
if __name__ == '__main__': main()

【问题讨论】:

标签: python python-3.x pyserial carriage-return eol


【解决方案1】:

使用简单的循环阅读怎么样?

def readData():
    buffer = ""
    while True:
        oneByte = ser.read(1)
        if oneByte == b"\r":    #method should returns bytes
            return buffer
        else:
            buffer += oneByte.decode("ascii")

您可以查看 Pyserial 包中的 serialutil.py 文件,它们使用相同的方法来实现方法read_until

【讨论】:

  • 由于性能糟糕,我不建议将其作为通用解决方案,但现在我们正在谈论低速串行接口,它可能会起作用。
  • 你的意思是\r,而不是\n
  • @juhist 我使用这种方法通过 RS232 与万用表等进行通信,其中响应时间超过 100 毫秒,在这种情况下这对性能绝对没有影响。
  • AttributeError: 'str' 对象没有属性 'append'
  • @juhist 再次修复。
【解决方案2】:

使用 read_until() 代替:

ser.read_until(b'\r')

小心,不要忘记 b。否则,即使它读取 '\r',该函数也不会返回,直到达到端口上设置的超时时间。

【讨论】:

    【解决方案3】:

    来自the docs for readline()

    对于二进制文件,行终止符总是b'\n';对于文本文件,open()newline 参数可用于选择识别的行终止符。

    当然,你不能在这里使用open。但是你可以做的是使用io.TextIOWrapper将字节流转换为文本流:

    ser_text = io.TextIOWrapper(ser, newline='\r')
    ser_text.readline()
    

    【讨论】:

    • 是否需要BufferedRWPair
    • 嗯,实际上,刚刚意识到即使使用该代码它仍然等待超时。我会坚持使用循环。我可以看到发生了什么。
    • 那为什么不把超时时间设为0呢?
    • 不断收到AttributeError: 'Serial' object has no attribute 'read1' 错误...
    • @spitz:我会为此向 pyserial 提交错误/功能请求
    猜你喜欢
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    • 2010-10-05
    • 2017-10-18
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    相关资源
    最近更新 更多