raw_input 无需按 Enter 键

2024-12-31 08:37:00
admin
原创
58
摘要:问题描述:我在 Python 中使用raw_input与 shell 中的用户交互。c = raw_input('Press s or n to continue:') if c.upper() == 'S': print 'YES' 它按预期工作,但用户在按下“s”后必须在 shell 中按下回车键...

问题描述:

我在 Python 中使用raw_input与 shell 中的用户交互。

c = raw_input('Press s or n to continue:')
if c.upper() == 'S':
    print 'YES'

它按预期工作,但用户在按下“s”后必须在 shell 中按下回车键。有没有办法从用户输入中完成我需要的操作,而无需在 shell 中按下回车键?我使用的是 *nixes 机器。


解决方案 1:

在 Windows 下,您需要msvcrt模块,具体来说,从您描述问题的方式来看,函数msvcrt.getch:

读取按键并返回结果字符。控制台不会回显任何内容。如果按键尚未可用,此调用将阻塞,但不会等待按下 Enter。

(等等——请参阅我刚才指出的文档)。对于 Unix,请参阅例如此配方,了解构建类似函数的简单方法getch(另请参阅该配方评论线程中的几种替代方案等)。

解决方案 2:

实际上,与此同时(从这个帖子开始算起已经快 10 年了),一个名为pynput 的跨平台模块出现了。下面是第一个版本 - 即仅适用于小写字母“s”。我在 Windows 上测试过它,但我几乎 100% 肯定它应该可以在 Linux 上运行。

from pynput import keyboard

print('Press s or n to continue:')

with keyboard.Events() as events:
    # Block for as much as possible
    event = events.get(1e6)
    if event.key == keyboard.KeyCode.from_char('s'):
        print("YES")

解决方案 3:

Python 不提供现成的多平台解决方案。

如果您使用的是 Windows,您可以尝试使用msvcrt:

import msvcrt
print 'Press s or n to continue:
'
input_char = msvcrt.getch()
if input_char.upper() == 'S': 
   print 'YES'

解决方案 4:

类Unix操作系统(包括Linux)的标准库解决方案:

def getch():
    import sys, termios

    fd = sys.stdin.fileno()
    orig = termios.tcgetattr(fd)

    new = termios.tcgetattr(fd)
    new[3] = new[3] & ~termios.ICANON
    new[6][termios.VMIN] = 1
    new[6][termios.VTIME] = 0

    try:
        termios.tcsetattr(fd, termios.TCSAFLUSH, new)
        return sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSAFLUSH, orig)

其工作原理是在从终端读取之前将终端置于非规范输入模式。

不回显用户输入的替代解决方案(例如,如果用户按下zz则不会出现在屏幕上):

def getch():
    import sys, termios, tty

    fd = sys.stdin.fileno()
    orig = termios.tcgetattr(fd)

    try:
        tty.setcbreak(fd)  # or tty.setraw(fd) if you prefer raw mode's behavior.
        return sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSAFLUSH, orig)

使用示例:

print('Press s or n to continue: ', end='', flush=True)
c = getch()
print()
if c.upper() == 'S':
    print('YES')

解决方案 5:

curses也可以做到这一点:

import curses, time

def input_char(message):
    try:
        win = curses.initscr()
        win.addstr(0, 0, message)
        while True: 
            ch = win.getch()
            if ch in range(32, 127): 
                break
            time.sleep(0.05)
    finally:
        curses.endwin()
    return chr(ch)

c = input_char('Do you want to continue? y/[n]')
if c.lower() in ['y', 'yes']:
    print('yes')
else:
    print('no (got {})'.format(c))

解决方案 6:

为了获取单个字符,我使用了getch,但我不知道它是否在 Windows 上运行。

解决方案 7:

使用 readchar:

import readchar

key = readchar.readkey()

if key == "a":
  print("text")

https://pypi.org/project/readchar/至网页

解决方案 8:

msvcrt您还可以使用WConio来代替模块:

>>> import WConio
>>> ans = WConio.getkey()
>>> ans
'y'

解决方案 9:

顺便提一下,msvcrt.kbhit() 返回一个布尔值,用于确定键盘上的任何键当前是否被按下。

因此,如果您正在制作游戏或其他东西,并希望通过按键来执行操作但不完全停止游戏,则可以在 if 语句中使用 kbhit() 来确保仅当用户真正想要执行某项操作时才检索该键。

Python 3 中的一个例子:

# this would be in some kind of check_input function
if msvcrt.kbhit():
    key = msvcrt.getch().decode("utf-8").lower() # getch() returns bytes data that we need to decode in order to read properly. i also forced lowercase which is optional but recommended
    if key == "w": # here 'w' is used as an example
        # do stuff
    elif key == "a":
        # do other stuff
    elif key == "j":
        # you get the point

解决方案 10:

我知道这已经过时了,但这个解决方案对我来说还不够好。我需要一个支持跨平台无需安装任何外部 Python 包的解决方案。

我的解决方案是,以防其他人看到这篇文章

参考:https://github.com/unfor19/mg-tools/blob/master/mgtools/get_key_pressed.py

from tkinter import Tk, Frame


def __set_key(e, root):
    """
    e - event with attribute 'char', the released key
    """
    global key_pressed
    if e.char:
        key_pressed = e.char
        root.destroy()


def get_key(msg="Press any key ...", time_to_sleep=3):
    """
    msg - set to empty string if you don't want to print anything
    time_to_sleep - default 3 seconds
    """
    global key_pressed
    if msg:
        print(msg)
    key_pressed = None
    root = Tk()
    root.overrideredirect(True)
    frame = Frame(root, width=0, height=0)
    frame.bind("<KeyRelease>", lambda f: __set_key(f, root))
    frame.pack()
    root.focus_set()
    frame.focus_set()
    frame.focus_force()  # doesn't work in a while loop without it
    root.after(time_to_sleep * 1000, func=root.destroy)
    root.mainloop()
    root = None  # just in case
    return key_pressed


def __main():
        c = None
        while not c:
                c = get_key("Choose your weapon ... ", 2)
        print(c)

if __name__ == "__main__":
    __main()

解决方案 11:

如果您可以使用外部库,blessed(跨平台)可以很容易地做到这一点:

from blessed import Terminal

term = Terminal()

with term.cbreak(): # set keys to be read immediately 
    print("Press any key to continue")
    inp = term.inkey() # wait and read one character

请注意,在with块内,终端的行编辑功能将被禁用。

cbreak、的文档inkey以及的示例inkey

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   990  
  在项目管理领域,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节,它不仅验证了项目团队的专业能力,还直接关系到项目的成功与否。在这一评审过程中,沟通技巧的运用至关重要。有效的沟通不仅能够确保信息的准确传递,还能增强团队协作,提升评审效率。本文将深入探讨CDCP...
华为IPD流程   26  
  IPD(Integrated Product Development,集成产品开发)是一种以客户需求为核心、跨部门协同的产品开发模式,旨在通过高效的资源整合和流程优化,提升产品开发的成功率和市场竞争力。在IPD培训课程中,掌握关键成功因素是确保团队能够有效实施这一模式的核心。以下将从五个关键成功因素展开讨论,帮助企业和...
IPD项目流程图   27  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司在其全球化进程中逐步构建和完善的一套高效产品开发管理体系。这一流程不仅帮助华为在技术创新和产品交付上实现了质的飞跃,还为其在全球市场中赢得了显著的竞争优势。IPD的核心在于通过跨部门协作、阶段性评审和市场需求驱动,确保...
华为IPD   26  
  华为作为全球领先的通信技术解决方案提供商,其成功的背后离不开一套成熟的管理体系——集成产品开发(IPD)。IPD不仅是一种产品开发流程,更是一种系统化的管理思想,它通过跨职能团队的协作、阶段评审机制和市场需求驱动的开发模式,帮助华为在全球市场中脱颖而出。从最初的国内市场到如今的全球化布局,华为的IPD体系在多个领域展现...
IPD管理流程   53  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用