【问题标题】:Python Serial: How to use the read or readline function to read more than 1 character at a timePython Serial:如何使用 read 或 readline 函数一次读取多个字符
【发布时间】:2026-01-17 04:00:01
【问题描述】:

我无法使用我的程序读取多个字符,我似乎无法弄清楚我的程序出了什么问题。

import serial

ser = serial.Serial(
    port='COM5',\
    baudrate=9600,\
    parity=serial.PARITY_NONE,\
    stopbits=serial.STOPBITS_ONE,\
    bytesize=serial.EIGHTBITS,\
        timeout=0)

print("connected to: " + ser.portstr)
count=1

while True:
    for line in ser.read():

        print(str(count) + str(': ') + chr(line) )
        count = count+1

ser.close()

这是我得到的结果

connected to: COM5
1: 1
2: 2
3: 4
4: 3
5: 1

其实我早就料到了

connected to: COM5
1:12431
2:12431

类似于上面提到的东西,它可以同时读取多个字符,而不是一个一个。

【问题讨论】:

  • *.com/questions/59564715/… 请任何人指导我
  • 在我找到的所有文档中,没有人指定我应该写“port = 'COM5'”,而不仅仅是 dev/usb0 或类似的。谢谢!

标签: python serial-port readline pyserial


【解决方案1】:

串行一次发送 8 位数据,转换为 1 个字节,1 个字节表示 1 个字符。

您需要实现自己的方法,该方法可以将字符读入缓冲区,直到到达某个标记。约定是发送类似12431\n 的消息,表示一行。

所以你需要做的是实现一个缓冲区来存储X个字符,一旦你到达\n,就在行上执行你的操作,然后继续将下一行读入缓冲区。

注意您将不得不处理缓冲区溢出的情况,即当收到的行比您的缓冲区长时等...

编辑

import serial

ser = serial.Serial(
    port='COM5',\
    baudrate=9600,\
    parity=serial.PARITY_NONE,\
    stopbits=serial.STOPBITS_ONE,\
    bytesize=serial.EIGHTBITS,\
        timeout=0)

print("connected to: " + ser.portstr)

#this will store the line
line = []

while True:
    for c in ser.read():
        line.append(c)
        if c == '\n':
            print("Line: " + ''.join(line))
            line = []
            break

ser.close()

【讨论】:

  • 嗨,你能给我一些关于缓冲的指导吗?我现在真的很困惑。
  • 我编辑了代码,看看。请记住一件事,上面的代码会一直读入line 数组,直到看到\n 字符,因此请确保在您的串行设备中发送\n
  • 嗨,上面的代码似乎不起作用。它说 char 未定义。
  • 现在试试,我应该有'c'的时候有char,只要确保你的串行程序确实在每行之后发送'\n'个字符
  • “您需要实现自己的方法,该方法可以将字符读入缓冲区直到到达某个标记” - 这正是serial.readline 所做的吗?跨度>
【解决方案2】:

我发现了几个问题。

第一:

ser.read() 一次只会返回 1 个字节。

如果您指定计数

ser.read(5)

它将读取 5 个字节(如果在 5 个字节到达之前发生超时,则更少。)

如果您知道您的输入始终以 EOL 字符正确终止, 更好的方法是使用

ser.readline()

这将继续读取字符,直到收到 EOL。

第二:

即使你让 ser.read() 或 ser.readline() 返回多个字节, 由于您正在迭代返回值,因此您将 仍然一次处理一个字节。

摆脱

for line in ser.read():

然后说:

line = ser.readline()

【讨论】:

  • 嗨,当我使用 line=ser.readline() 时,它总是要求我输入一个整数 print(str(count) + str(': ') + chr(line) ) TypeError : 需要一个整数
  • chr(line) 需要一个整数参数。你给它一个字符串。
【解决方案3】:

我从我的 arduino uno(0-1023 数字)那里收到了一些日期。 使用来自 1337holiday、jwygralak67 的代码和其他来源的一些提示:

import serial
import time

ser = serial.Serial(
    port='COM4',\
    baudrate=9600,\
    parity=serial.PARITY_NONE,\
    stopbits=serial.STOPBITS_ONE,\
    bytesize=serial.EIGHTBITS,\
        timeout=0)

print("connected to: " + ser.portstr)

#this will store the line
seq = []
count = 1

while True:
    for c in ser.read():
        seq.append(chr(c)) #convert from ANSII
        joined_seq = ''.join(str(v) for v in seq) #Make a string from array

        if chr(c) == '\n':
            print("Line " + str(count) + ': ' + joined_seq)
            seq = []
            count += 1
            break


ser.close()

【讨论】:

  • 我认为你的评论#convert from ansii 应该是#convert from ascii
  • 这个 chr(c) 为我解决了几天后的问题。我有一个 ATTiny85 发送一个 int 到一个 ATTiny45 发送这个数据到一个 Raspberry Pi 0。全部使用串行通信。我只是在检查为什么在我发送 0 时它显示 48。ASCII 于 1963 年发布。总是,回到源头。谢谢。
【解决方案4】:

我用这个小方法用 Python 读取 Arduino 串口监视器

import serial
ser = serial.Serial("COM11", 9600)
while True:
     cc=str(ser.readline())
     print(cc[2:][:-5])

【讨论】:

  • 很好,我需要清理那个响应,好一个!我认为对于未来的读者来说,在您的回答中值得一提的是您的代码究竟执行了什么。
  • 我假设您使用cc[2:][:-5] 剥离b'\r\n'。使用.decode("utf-8") 不是更好吗?