如何让python等待按下的键

时间:2009-06-11 20:09:19

标签: python wait keyboard-input

我希望我的脚本等到用户按任意键。

我该怎么做?

12 个答案:

答案 0 :(得分:406)

在Python 3中,不存在raw_input()。所以,只需使用:

input("Press Enter to continue...")

在Python 2中,您应该使用raw_input(),因为input(prompt)相当于eval(raw_input(prompt))

raw_input("Press Enter to continue...")

这只等待用户按Enter键,因此您可能希望使用 msvcrt ((仅限Windows / DOS)msvcrt模块允许您访问Microsoft Visual中的许多功能C / C ++运行时库(MSVCRT)):

import msvcrt as m
def wait():
    m.getch()

这应该等待按键。

答案 1 :(得分:314)

在Python 2中执行此操作的一种方法是使用raw_input()

raw_input("Press Enter to continue...")

在python3中,它只是input()

答案 2 :(得分:50)

在我的linux机器上,我使用以下代码。这类似于我在其他地方看到的代码(例如在旧的python常见问题解答中),但是代码在紧密的循环中旋转,而这个代码没有,并且有很多奇怪的角落情况,代码没有考虑到这一点代码确实。

def read_single_keypress():
    """Waits for a single keypress on stdin.

    This is a silly function to call if you need to do it a lot because it has
    to store stdin's current setup, setup stdin for reading single keystrokes
    then read the single keystroke then revert stdin back after reading the
    keystroke.

    Returns a tuple of characters of the key that was pressed - on Linux, 
    pressing keys like up arrow results in a sequence of characters. Returns 
    ('\x03',) on KeyboardInterrupt which can happen when a signal gets
    handled.

    """
    import termios, fcntl, sys, os
    fd = sys.stdin.fileno()
    # save old state
    flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
    attrs_save = termios.tcgetattr(fd)
    # make raw - the way to do this comes from the termios(3) man page.
    attrs = list(attrs_save) # copy the stored version to update
    # iflag
    attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
                  | termios.ISTRIP | termios.INLCR | termios. IGNCR
                  | termios.ICRNL | termios.IXON )
    # oflag
    attrs[1] &= ~termios.OPOST
    # cflag
    attrs[2] &= ~(termios.CSIZE | termios. PARENB)
    attrs[2] |= termios.CS8
    # lflag
    attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
                  | termios.ISIG | termios.IEXTEN)
    termios.tcsetattr(fd, termios.TCSANOW, attrs)
    # turn off non-blocking
    fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
    # read a single keystroke
    ret = []
    try:
        ret.append(sys.stdin.read(1)) # returns a single character
        fcntl.fcntl(fd, fcntl.F_SETFL, flags_save | os.O_NONBLOCK)
        c = sys.stdin.read(1) # returns a single character
        while len(c) > 0:
            ret.append(c)
            c = sys.stdin.read(1)
    except KeyboardInterrupt:
        ret.append('\x03')
    finally:
        # restore old state
        termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
        fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
    return tuple(ret)

答案 3 :(得分:27)

如果您可以使用,取决于系统命令,您可以使用以下内容:

Linux的:

os.system('read -s -n 1 -p "Press any key to continue..."')
print

视窗:

os.system("pause")

答案 4 :(得分:23)

只需使用

input("Press Enter to continue...")

将导致语法错误:解析时预期的EOF。

简单修复使用:

try:
    input("Press enter to continue")
except SyntaxError:
    pass

答案 5 :(得分:14)

python manual提供以下内容:

import termios, fcntl, sys, os
fd = sys.stdin.fileno()

oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)

oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

try:
    while 1:
        try:
            c = sys.stdin.read(1)
            print "Got character", repr(c)
        except IOError: pass
finally:
    termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
    fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

可以归入您的用例。

答案 6 :(得分:13)

我不知道采用独立于平台的方式,但在Windows下,如果使用msvcrt模块,则可以使用其getch函数:

import msvcrt
c = msvcrt.getch()
print 'you entered', c

mscvcrt还包括非阻塞kbhit()函数,用于查看是否按下键而不等待(不确定是否存在相应的curses函数)。在UNIX下,有curses包,但不确定是否可以在不使用它的情况下使用它来进行所有屏幕输出。此代码适用于UNIX:

import curses
stdscr = curses.initscr()
c = stdscr.getch()
print 'you entered', chr(c)
curses.endwin()

请注意,curses.getch()返回按下的键的序号,以使其具有相同的输出。

答案 7 :(得分:12)

跨平台,Python 2/3代码:

# import sys, os

def wait_key():
    ''' Wait for a key press on the console and return it. '''
    result = None
    if os.name == 'nt':
        import msvcrt
        result = msvcrt.getch()
    else:
        import termios
        fd = sys.stdin.fileno()

        oldterm = termios.tcgetattr(fd)
        newattr = termios.tcgetattr(fd)
        newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
        termios.tcsetattr(fd, termios.TCSANOW, newattr)

        try:
            result = sys.stdin.read(1)
        except IOError:
            pass
        finally:
            termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)

    return result

我删除了fctl / non-blocking的内容,因为它提供了IOError,我并不需要它。我特意使用此代码,因为我希望它阻止。 ;)

答案 8 :(得分:2)

我是python的新手,我一直在想我太愚蠢了,无法重现这里提出的最简单的建议。 事实证明,有一个人应该知道的陷阱:

当从IDLE执行python脚本时,某些IO命令似乎表现完全不同(因为实际上没有终端窗口)。

EG。 msvcrt.getch是非阻塞的,总是返回$ ff。 这已经在很久以前就已经报道了(参见例如https://bugs.python.org/issue9290) - 并且它被标记为已修复,不知怎的问题似乎在当前版本的python / IDLE中仍然存在。

因此,如果上面发布的任何代码对您不起作用,请尝试手动运行脚本, NOT来自IDLE

答案 9 :(得分:2)

如果您要等待输入(因此用户敲击键盘不会引起意外的事情),请使用

sys.stdin.readline()

答案 10 :(得分:1)

如果你想看看他们是否按下了一个确切的键(比如'b'),请执行以下操作:

while True:
    choice = raw_input("> ")

    if choice == 'b' :
        print "You win"
        input("yay")
        break

答案 11 :(得分:0)

os.system似乎总是调用sh,它不识别读取的s和n选项。但是,read命令可以传递给bash:

 os.system("""bash -c 'read -s -n 1 -p "Press any key to continue..."'""")