读取没有Curses模块的方向键

时间:2018-07-11 01:04:42

标签: python python-3.x module arrow-keys

因此,我正在编写一个需要箭头键但不能使用curses或chr函数的程序。有任何简单的方法可以做到这一点吗?

顺便说一句,我已经尝试过inp.key_UP,但这似乎不起作用。另外我在Mac上,因此gtsrc无法正常工作。

2 个答案:

答案 0 :(得分:0)

当用户按下一个键时(除非您正在以非常低的水平阅读,例如Cocoa系统事件钩子),终端程序(通常是Terminal.app)将对其进行处理并向您的程序发送一个字节序列,您可以读取sys.stdin/dev/tty

使用默认设置:

  • 对于ASCII字母,数字等,该字节序列仅为一个字节,带有字符ord
  • 对于非ASCII字符,该字节序列是字符的UTF-8编码。 (在其他* nix上,您不能依赖于它是UTF-8,但在macOS上,可以。)
  • 对于特殊键(如箭头),该序列为ANSI standard escape sequences。例如,对于向上箭头,您将获得Cursor Up(\x1b[A)或Cursor Up 1(\x1b[1A)。 (您实际上不应该假定使用ANSI兼容的终端,甚至可以将Terminal.app配置为发送不同的内容,而是阅读$TERM并查找termcaps条目,但是如果您只关心Mac,则可以'几乎肯定会摆脱这个。)

因此,现在您只需要打开stdin/dev/tty作为未缓冲的原始二进制文件,将其置于原始模式(并确保在程序末尾将其还原),请阅读字节关闭,并识别ANSI控制序列。哦,而且如果用户的键盘上有不是ASCII的任何键,它们也将显示为多个字节,您必须将其解码为UTF-8。

以下是应证明的内容:

import termios
import tty

with open('/dev/tty', 'rb', buffering=0) as f:
    stashed = termios.tcgetattr(f.fileno())
    try:
        tty.setraw(f.fileno())
        while True:
            key = f.read(1)
            if key == b'\x03': # Control-C
                break
            if key == b'\x1b': # Escape
                buf = key
                while True:
                    key = f.read(1)
                    buf += key
                    # Cheating a bit; most sequences go until the first letter
                    if key.isalpha():
                        break
                if buf == b'\x1b[A':
                    print('Up arrow!')
                else:
                    print('Some other control sequence:', buf)
            # punting on UTF-8 decoding, treating non-ASCII as control chars
            elif b' ' <= key < b'\x80':
                print(key.decode())
            else:
                print('Some control or non-ASCII key', key)
    finally:
        termios.tcsetattr(f.fileno(), termios.TCSADRAIN, stashed)

如果这不能证明人们为什么通常使用诸如curses之类的更高级别的库,则寻找一些实际上可以正确执行termcap和locale内容的代码,而不是假设。 :)

答案 1 :(得分:-1)

我试图... 但是,您需要按Enter才能返回值。 祝你好运!

import sys

def get():
    x = sys.stdin.read(1)
    return x
while True: 

    key = get()
    print key