是否有办法从用户输入中读取单个字符?例如,他们在终端上按下一个键,它就会返回(有点像getch())。我知道Windows中有这个功能,但我想要跨平台的东西。


当前回答

如果你只是想按住屏幕,这样你就可以在终端上看到结果

input()

在代码的末尾,它将保存屏幕

其他回答

如果您想只注册一个键,即使用户按了多次或长时间按该键也要按。 为了避免获得多个按下的输入,使用while循环并传递它。

import keyboard

while(True):
  if(keyboard.is_pressed('w')):
      s+=1
      while(keyboard.is_pressed('w')):
        pass
  if(keyboard.is_pressed('s')):
      s-=1
      while(keyboard.is_pressed('s')):
        pass
  print(s)

这可能是上下文管理器的一个用例。不考虑Windows操作系统,以下是我的建议:

#!/usr/bin/env python3
# file: 'readchar.py'
"""
Implementation of a way to get a single character of input
without waiting for the user to hit <Enter>.
(OS is Linux, Ubuntu 14.04)
"""

import tty, sys, termios

class ReadChar():
    def __enter__(self):
        self.fd = sys.stdin.fileno()
        self.old_settings = termios.tcgetattr(self.fd)
        tty.setraw(sys.stdin.fileno())
        return sys.stdin.read(1)
    def __exit__(self, type, value, traceback):
        termios.tcsetattr(self.fd, termios.TCSADRAIN, self.old_settings)

def test():
    while True:
        with ReadChar() as rc:
            char = rc
        if ord(char) <= 32:
            print("You entered character with ordinal {}."\
                        .format(ord(char)))
        else:
            print("You entered character '{}'."\
                        .format(char))
        if char in "^C^D":
            sys.exit()

if __name__ == "__main__":
    test()

下面是ActiveState Recipes网站的链接,告诉你如何在Windows、Linux和OSX中读取单个字符:

getch()-类似于在Windows和Unix上从stdin读取的非缓冲字符

class _Getch:
    """Gets a single character from standard input.  Does not echo to the
screen."""
    def __init__(self):
        try:
            self.impl = _GetchWindows()
        except ImportError:
            self.impl = _GetchUnix()

    def __call__(self): return self.impl()


class _GetchUnix:
    def __init__(self):
        import tty, sys

    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch


class _GetchWindows:
    def __init__(self):
        import msvcrt

    def __call__(self):
        import msvcrt
        return msvcrt.getch()


getch = _Getch()

我相信这是一个最优雅的解决方案。

import os

if os.name == 'nt':
    import msvcrt
    def getch():
        return msvcrt.getch().decode()
else:
    import sys, tty, termios
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    def getch():
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

然后在代码中使用它:

if getch() == chr(ESC_ASCII_VALUE):
    print("ESC!")

接受的答案对我来说并不是那么好(我按住一个键,什么都不会发生,然后我按下另一个键,它就会工作)。

在学习了curses模块之后,这似乎是正确的方法。现在它可以通过Windows -游标(通过pip可用)用于Windows,因此您可以以与平台无关的方式进行编程。下面这个例子是受YouTube上这个教程的启发:

import curses                                                                                                                                       
def getkey(stdscr):
    curses.curs_set(0)
    while True:
        key = stdscr.getch()
        if key != -1:
            break
    return key

if __name__ == "__main__":
    print(curses.wrapper(getkey))

以.py扩展名保存,或在交互模式下运行curses.wrapper(getkey)。