You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中从stdin读取单个字符?(处理Arduino串口数据)

在Python中从stdin读取单个字符(适配Arduino串口数据场景)

刚好我之前也处理过类似的串口数据读取需求,知道默认的行缓冲机制会给单字符读取带来麻烦,下面分场景给你几种可行的方案:

核心问题:默认stdin的行缓冲

默认情况下,终端的stdin是行缓冲模式——也就是说,只有当按下回车时,输入的内容才会被传给Python程序,这显然不符合你读取单个串口字符的需求。所以我们需要先修改终端的缓冲模式,或者用平台特定的方法绕过缓冲。


方案1:Linux/macOS 下用 termios 模块修改终端属性

这个方法能直接修改终端的输入模式,让它变成字符缓冲(输入一个字符就立刻传给程序),非常适合串口数据的实时读取。

示例代码:

import sys
import termios
import tty

def get_single_char():
    # 保存当前终端属性
    old_attr = termios.tcgetattr(sys.stdin)
    try:
        # 设置终端为字符缓冲模式
        tty.setcbreak(sys.stdin.fileno())
        # 读取单个字符
        char = sys.stdin.read(1)
        return char
    finally:
        # 恢复终端原属性,避免影响后续操作
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr)

# 针对你的Arduino场景:读取<和>包裹的内容
def read_arduino_data():
    buffer = []
    while True:
        char = get_single_char()
        if char == '<':
            # 遇到起始符,清空缓冲区开始收集
            buffer = []
        elif char == '>':
            # 遇到结束符,返回收集到的内容
            return ''.join(buffer)
        else:
            # 中间字符加入缓冲区
            buffer.append(char)

# 测试:读取数据并写入文件
if __name__ == "__main__":
    with open("arduino_data.txt", "a") as f:
        while True:
            data = read_arduino_data()
            print(f"收到数据:{data}")
            f.write(data + "\n")
            f.flush()

方案2:Windows 下用 msvcrt 模块

Windows系统没有termios,我们可以用内置的msvcrt模块来实现单字符读取,它会直接从控制台读取单个字符,不需要处理缓冲问题。

示例代码:

import sys
import msvcrt

def get_single_char():
    # 读取单个字符,不需要回车
    return msvcrt.getch().decode('utf-8')

# 同样的Arduino数据读取逻辑
def read_arduino_data():
    buffer = []
    while True:
        char = get_single_char()
        if char == '<':
            buffer = []
        elif char == '>':
            return ''.join(buffer)
        else:
            buffer.append(char)

# 写入文件的逻辑和上面一致
if __name__ == "__main__":
    with open("arduino_data.txt", "a") as f:
        while True:
            data = read_arduino_data()
            print(f"收到数据:{data}")
            f.write(data + "\n")
            f.flush()

方案3:跨平台简化版(适合串口转发场景)

如果你用的串口工具已经把串口数据直接转发到stdin(比如没有额外的行缓冲),也可以尝试用sys.stdin.read(1)直接读取,但要注意关闭Python的缓冲:

import sys

# 关闭stdin的缓冲
sys.stdin = open(sys.stdin.fileno(), 'rb', buffering=0)

def get_single_char():
    return sys.stdin.read(1).decode('utf-8')

# 后续的读取逻辑和前面一致

不过这个方法的兼容性不如前两种,因为有些终端环境还是会强制行缓冲,所以优先推荐前两种平台特定的方案。


额外提示(针对你的Arduino场景)

  • 确保Arduino的串口波特率和转发工具的波特率一致,避免出现乱码;
  • 如果你的Arduino发送的是二进制数据,记得把读取的字节直接处理,不要解码成字符串;
  • 写入文件时记得调用flush(),避免数据因为文件缓冲而延迟写入。

内容的提问来源于stack exchange,提问作者Philipp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:21:48