执行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()
原因分析
- 终端模式未正常恢复:curtsies库的
Input(keynames='curses')会将终端切换为非回显模式(关闭输入内容的实时显示),正常情况下with语句块退出时会自动恢复终端默认设置。但由于读取输入的线程被设为daemon线程,主程序退出时该线程会被强制终止,with块的终端恢复逻辑无法执行,导致终端一直停留在非回显状态。 - 异常处理失效:代码中
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
相关产品推荐
相关产品推荐

