python tty.setraw Ctrl + C不起作用(提取)

Soo*_*hin 5 python getch

这是我的代码。

def getch():
    fd = sys.stdin.fileno()
    old_Settings = termios.tcgetattr(fd)
    try: 
        tty.setraw(sys.stdin.fileno())
        sys.stdin.flush()
    except KeyboardInterrupt:
        print ("[Error] Abnormal program termination")
    finally:
        termios.tcsetattr(fd,termios.TCSADRAIN,old_settings)
    return ch
Run Code Online (Sandbox Code Playgroud)

在此代码中,KeyboardInterrupt异常不起作用。

谢谢

aba*_*ert 5

是的,当您将TTY设置为原始模式时,或者特别是在禁用termios设置时,您将ISIG不再获得相应的行为:

  ISIG   When any of the characters INTR, QUIT, SUSP, or DSUSP are
         received, generate the corresponding signal.
Run Code Online (Sandbox Code Playgroud)

换句话说,在大多数终端中,该字符INTR^C不再产生SIGINT信号,这是Python用于引发的信号KeyboardInterrupt

这样,全屏程序emacs就可以^C用作控制角色而不仅仅是退出。

因此,有两种选择:


而不是调用setraw,而是设置所需的确切termios标志集,并确保不要禁用ISIG

值得一看的是Python的源代码,tty.setraw以确切地了解它的作用,并将其用作基准。

如果没有,您可以做完全相同的事情ISIG。但实际上,您应该阅读文档以了解这些内容的含义。

并确保man termios在您自己的系统上不要在线搜索;Linux与macOS / * BSD的情况有些不同,即使同一OS的版本之间也存在细微的差异。

即使在阅读了文档并进行了自己的实验之后,也可能并不完全清楚每种设置都有什么作用。本文似乎做了不错的工作,解释了进入原始模式的内容以及每个相关标志的实际含义(尽管我只是快速浏览了一下,而且,您仍然需要阅读man termios适用于平台的内容)。


另外,您也可以^C手动处理。

您已经可以使用来同时读取一个字符sys.stdin.read(1),因此当有人按下时^C,您将要读取一个'\x03'字符。

发生这种情况时,您可以做任何您想做的事情,包括raise KeyboardInterrupt


附带说明一下,如果是Python 3,则可能要以二进制模式阅读:

ch = sys.stdin.buffer.raw.read(1)
sys.stdin.flush()
Run Code Online (Sandbox Code Playgroud)

(然后,您将检查b'\x03'而不是'\x03'。)

在文本模式下,即使它是UTF-8中的多字节字符(或任何语言环境),也应一次获得一个完整字符。乍一看似乎比较简单,但实际上可能会产生误导,因为单个字符仍然只能是按键的一部分。例如,在大多数终端上,向上箭头发送3个字符('\x1B[A', butread(1)`只会为您提供第一个字符。