python tty.setraw Ctrl + C 不起作用(获取)
python tty.setraw Ctrl + C doesn't work (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
在此代码中,KeyboardInterrupt 异常不起作用。
谢谢
是的,当您将 TTY 设置为原始模式时——或者,特别是当您禁用 termios
设置时 ISIG
——您将不再获得相应的行为:
ISIG When any of the characters INTR, QUIT, SUSP, or DSUSP are
received, generate the corresponding signal.
换句话说,字符 INTR
,即大多数终端中的 ^C
,不再生成 SIGINT
信号,即 is what Python uses to raise a KeyboardInterrupt
.
这就是像 emacs
这样的全屏程序可以使用 ^C
作为控制字符而不只是退出的方式。
所以,有两个选择:
不要调用 setraw
,而是设置你想要的一组 termios
标志,确保不要禁用 ISIG
。
值得查看 Python 的 tty.setraw
的源代码,以了解它到底做了什么,用作基准。
你可以在没有 ISIG
的情况下做同样的事情。但实际上,您应该阅读文档以了解其中每一项的含义。
并确保man termios
在您自己的系统上,不要在线搜索;在 Linux 与 macOS/*BSD 上有些不同,甚至在相同 OS.
的版本之间也存在细微差别
即使阅读了文档并自己进行了试验,也可能并不完全清楚每个设置的效果。 This article 似乎很好地解释了进入原始模式的内容,以及每个相关标志的实际含义(尽管我只是快速浏览了一下——而且。再一次,你仍然需要阅读 man termios
适用于您的平台)。
或者,您可以手动处理 ^C
。
您已经在使用 sys.stdin.read(1)
一次读取一个字符,因此当有人点击 ^C
时,您将读取一个 '\x03'
字符。
发生这种情况时,您可以为所欲为,包括 raise KeyboardInterrupt
。
附带说明,如果这是 Python 3,您可能希望以二进制模式阅读:
ch = sys.stdin.buffer.raw.read(1)
sys.stdin.flush()
(然后您将检查 b'\x03'
而不是 '\x03'
。当然。)
在文本模式下,您应该一次获取一个完整的字符,即使它是 UTF-8(或您的语言环境)中的多字节字符。起初 似乎 更简单——但这实际上可能会产生误导,因为单个字符仍然可能只是击键的一部分。例如,对于大多数终端,向上箭头发送 3 个字符 ('\x1B[A'
), but
read(1)` 只会给您第一个字符。
这是我的代码。
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
在此代码中,KeyboardInterrupt 异常不起作用。
谢谢
是的,当您将 TTY 设置为原始模式时——或者,特别是当您禁用 termios
设置时 ISIG
——您将不再获得相应的行为:
ISIG When any of the characters INTR, QUIT, SUSP, or DSUSP are received, generate the corresponding signal.
换句话说,字符 INTR
,即大多数终端中的 ^C
,不再生成 SIGINT
信号,即 is what Python uses to raise a KeyboardInterrupt
.
这就是像 emacs
这样的全屏程序可以使用 ^C
作为控制字符而不只是退出的方式。
所以,有两个选择:
不要调用 setraw
,而是设置你想要的一组 termios
标志,确保不要禁用 ISIG
。
值得查看 Python 的 tty.setraw
的源代码,以了解它到底做了什么,用作基准。
你可以在没有 ISIG
的情况下做同样的事情。但实际上,您应该阅读文档以了解其中每一项的含义。
并确保man termios
在您自己的系统上,不要在线搜索;在 Linux 与 macOS/*BSD 上有些不同,甚至在相同 OS.
即使阅读了文档并自己进行了试验,也可能并不完全清楚每个设置的效果。 This article 似乎很好地解释了进入原始模式的内容,以及每个相关标志的实际含义(尽管我只是快速浏览了一下——而且。再一次,你仍然需要阅读 man termios
适用于您的平台)。
或者,您可以手动处理 ^C
。
您已经在使用 sys.stdin.read(1)
一次读取一个字符,因此当有人点击 ^C
时,您将读取一个 '\x03'
字符。
发生这种情况时,您可以为所欲为,包括 raise KeyboardInterrupt
。
附带说明,如果这是 Python 3,您可能希望以二进制模式阅读:
ch = sys.stdin.buffer.raw.read(1)
sys.stdin.flush()
(然后您将检查 b'\x03'
而不是 '\x03'
。当然。)
在文本模式下,您应该一次获取一个完整的字符,即使它是 UTF-8(或您的语言环境)中的多字节字符。起初 似乎 更简单——但这实际上可能会产生误导,因为单个字符仍然可能只是击键的一部分。例如,对于大多数终端,向上箭头发送 3 个字符 ('\x1B[A'
), but
read(1)` 只会给您第一个字符。