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

Python 3执行input()方法时如何输入可删除换行符并通过异常终止输入

需求可以实现

默认的input()和sys.stdin.readlines()都基于行缓冲模式,该模式下换行符会被系统当做输入终止符,一旦输入就无法退格删除。我们可以通过修改终端的输入模式,自行逐字符处理输入来满足所有要求,核心逻辑是绕开系统默认的行缓冲规则,自己维护输入缓冲区。


实现思路

  1. 先保存终端的原始配置,避免程序异常退出后终端输入行为异常
  2. 将终端切换为cbreak模式(类Unix平台)或直接逐字符读取(Windows平台):该模式下输入不需要等待换行即可被程序捕获,同时保留Ctrl+C触发KeyboardInterrupt的能力
  3. 逐字符处理输入:
    • 普通字符(包括换行符)直接存入自定义缓冲区并回显
    • 退格字符触发时删除缓冲区最后一位,同时更新终端显示
    • 自定义输入终止快捷键(比如Ctrl+D,和系统shell默认行为一致),触发时返回缓冲区完整内容
  4. 无论流程正常结束还是被中断,都先恢复终端原始配置再退出

代码实现

适用Unix/Linux/macOS平台

import sys
import tty
import termios

def multi_line_input(prompt: str = "") -> str:
    fd = sys.stdin.fileno()
    # 保存终端原始配置
    original_attr = termios.tcgetattr(fd)
    buffer = []
    try:
        # 切换到cbreak模式,保留信号处理能力
        tty.setcbreak(fd)
        if prompt:
            sys.stdout.write(prompt)
            sys.stdout.flush()
        while True:
            char = sys.stdin.read(1)
            # 处理Ctrl+C终止输入
            if ord(char) == 3:
                raise KeyboardInterrupt
            # 处理退格
            elif char in ("\x7f", "\b"):
                if buffer:
                    buffer.pop()
                    # 同步更新终端显示
                    sys.stdout.write("\b \b")
                    sys.stdout.flush()
            # 处理Ctrl+D结束输入
            elif ord(char) == 4:
                sys.stdout.write("\n")
                sys.stdout.flush()
                return "".join(buffer)
            # 普通字符包括换行直接存入缓冲区
            else:
                buffer.append(char)
                sys.stdout.write(char)
                sys.stdout.flush()
    finally:
        # 强制恢复终端原始配置
        termios.tcsetattr(fd, termios.TCSADRAIN, original_attr)

# 测试
if __name__ == "__main__":
    try:
        content = multi_line_input("请输入内容(Ctrl+D结束输入,Ctrl+C终止):\n")
        print(f"\n输入的原始内容为:\n{repr(content)}")
    except KeyboardInterrupt:
        print("\n输入已终止")
        sys.exit(0)

适用Windows平台

import sys
import msvcrt

def multi_line_input(prompt: str = "") -> str:
    buffer = []
    if prompt:
        sys.stdout.write(prompt)
        sys.stdout.flush()
    while True:
        char = msvcrt.getwch()
        # 处理Ctrl+C终止输入
        if ord(char) == 3:
            raise KeyboardInterrupt
        # 处理退格
        elif char in ("\x7f", "\b"):
            if buffer:
                buffer.pop()
                sys.stdout.write("\b \b")
                sys.stdout.flush()
        # 处理Ctrl+D结束输入
        elif ord(char) == 4:
            sys.stdout.write("\n")
            sys.stdout.flush()
            return "".join(buffer)
        # 处理回车换行
        elif char == "\r":
            buffer.append("\n")
            sys.stdout.write("\n")
            sys.stdout.flush()
        # 普通字符存入缓冲区
        else:
            buffer.append(char)
            sys.stdout.write(char)
            sys.stdout.flush()

# 测试
if __name__ == "__main__":
    try:
        content = multi_line_input("请输入内容(Ctrl+D结束输入,Ctrl+C终止):\n")
        print(f"\n输入的原始内容为:\n{repr(content)}")
    except KeyboardInterrupt:
        print("\n输入已终止")
        sys.exit(0)

效果验证

  • 输入过程中敲回车会直接插入换行符,敲退格可以删除包括换行在内的所有已输入字符
  • 按Ctrl+C会直接触发KeyboardInterrupt终止输入流程
  • 全程没有使用sys.stdin.readlines(),完全符合要求

内容的提问来源于stack exchange,提问作者Chen-Y0y0

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:12:03