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

执行Python3脚本后Linux终端无法显示输入的原因及解决方法

问题描述

在Raspberry Pi OS bullseye 32位系统的KDE Konsole终端中运行以下Python脚本后,无论通过Ctrl+C退出还是等待脚本执行完毕,当前终端标签会出现输入文本不可见但命令仍能响应的问题,新开终端标签则正常工作。

脚本代码及仓库链接:https://gitlab.com/papiris/gcode-motor-stutter-generator

#!/usr/bin/env python3

from sys import stdout, stdin 
from curtsies import Input
from threading import Thread
from queue import Queue, Empty

### non-blocking read of stdin
def enqueue_input(stdin, queue):
    try:
        with Input(keynames='curses') as input_generator:
            for _input in iter(input_generator):
                queue.put(_input)

    except keyboardInterrupt:
        sys.exit(1)

q=Queue()
t = Thread(target=enqueue_input, args=(stdin, q))
t.daemon = True # thread dies with the program
t.start()


def main():
    while True:
        try:
            input_key = q.get(timeout=2)
        except Empty:
            print(f'printing continuously') 
            pass
        
        else:
            if input_key == 'n':
                print('extrusion loop stopped, moving on')
                break
        

if __name__ == "__main__":
    main()
原因分析
  1. 终端模式未正常恢复:curtsies库的Input(keynames='curses')会将终端切换为非回显模式(关闭输入内容的实时显示),正常情况下with语句块退出时会自动恢复终端默认设置。但由于读取输入的线程被设为daemon线程,主程序退出时该线程会被强制终止,with块的终端恢复逻辑无法执行,导致终端一直停留在非回显状态。
  2. 异常处理失效:代码中keyboardInterrupt拼写错误(应为KeyboardInterrupt),且未导入sys模块,导致Ctrl+C触发中断时无法正常捕获并执行清理逻辑,进一步导致终端状态无法恢复。
解决方案

临时恢复终端(无需修改脚本)

在出现问题的终端中直接执行以下命令,即可快速恢复终端的输入回显功能:

stty sane

永久修复(修改脚本)

调整脚本逻辑,确保终端状态能被正确恢复,具体修改如下:

#!/usr/bin/env python3

import sys
from sys import stdin 
from curtsies import Input
from threading import Thread, Event
from queue import Queue, Empty

def enqueue_input(queue, stop_event):
    try:
        with Input(keynames='curses') as input_generator:
            for _input in iter(input_generator):
                if stop_event.is_set():
                    break
                queue.put(_input)
    except KeyboardInterrupt:
        pass

def main():
    q = Queue()
    stop_event = Event()
    t = Thread(target=enqueue_input, args=(q, stop_event))
    t.start()

    try:
        while True:
            try:
                input_key = q.get(timeout=2)
            except Empty:
                print('printing continuously')
                pass
            else:
                if input_key == 'n':
                    print('extrusion loop stopped, moving on')
                    break
    except KeyboardInterrupt:
        print('\nReceived interrupt, exiting...')
    finally:
        stop_event.set()
        t.join()

if __name__ == "__main__":
    main()

修改说明:

  • 添加stop_event事件,用于优雅终止输入线程,避免线程被强制杀死导致清理逻辑失效;
  • 主程序捕获KeyboardInterrupt,在finally块中通知线程停止并等待线程结束,确保with Input的终端恢复逻辑正常执行;
  • 修正sys模块导入和KeyboardInterrupt拼写错误,保证异常处理生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 22:30:55