如何让python等待按下的键?


Answers:


542

Python 3中使用input()

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

Python 2中使用raw_input()

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

不过,这仅等待用户按下Enter键。

可能要使用msvcrt((仅Windows / DOS)使用msvcrt模块可以访问Microsoft Visual C / C ++运行时库(MSVCRT)中的许多功能):

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

这应该等待按键。

附加信息:

Python 3 raw_input()中不存在

在Python 2 input(prompt)中等效于eval(raw_input(prompt))


54
当我尝试在Python 2.7中执行此操作时出现此错误:“ SyntaxError:解析时出现意外的EOF”
Jon Tirsen 2014年

8
@ Solarsaturn9和越来越多的人没有。因此,这个答案对我以及这里的其他许多人都无效。
ctrl-alt-delor

5
使用input()的@richard也应该在其他平台上工作。当第一个解决方案是多平台时,停靠点以提供仅Windows解决方案是荒谬的。
Cory Buckley

7
@ Solarsaturn9再次阅读问题并回答:input如果按下任何键,则只有在按下Enter的情况下才继续。
ctrl-alt-delor

13
@JonTirsen,这是因为Python 2.7具有一个称为input的函数,该函数可以评估您输入的字符串。要解决此问题,请使用raw_input
Samy Bencherif


56

在我的Linux机器上,我使用以下代码。这类似于我在其他地方看到的代码(例如,在旧的python FAQ中),但是该代码在一个紧密的循环中旋转,其中该代码不起作用,并且在很多奇怪的情况下,代码无法解决这个问题代码呢。

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)

虽然这是我在这里最喜欢的答案,但就像其他人一样,他们并没有抓住转变,控制等问题
马拉

1
@Mala在纯Python中几乎是不可能的;也许您应该编写一个C模块?

我在系统上的键盘中断(Ctrl-C)上收到“ \ x03”。
GDR

1
ctrl-c是ascii 3,因此可以预期。如果要在ctrl-c上发出信号,简单的解决方案是将if ord(returned_value)== 3:os.kill(os.getpid(),signal.SIGINT),但也可以关闭信号处理通过attrs [0] | = termios.BRKINT,attrs [3]!= termios.ISIG,并摆脱除KeyboardInterrupt之外的处理。注–为了纪念您的查询,我将KeyboardInterrupt的返回值更改为“ \ x03”(因为这使此代码始终返回字符串)。
mheyman '18

上面的代码如何进行调整,以便为复杂的按键(如“ Page Up”或“ Left Arrow”)返回一个元组?
德里克(Derek)

33

如果可以,请根据系统命令使用以下命令:

Linux:

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

视窗:

import os
os.system("pause")

如果您要一直运行直到发出信号(如SIGINT),也可以检查from的返回值system,然后调用sys.exit(0)
James Taylor

29

只需使用

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

解析时将导致SyntaxError:预期的EOF。

简单修复方法:

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

5
不要input在python 2中使用-正确的功能是raw_input。在python 2中,input等效于eval(raw_input())
Blorgbeard在

2
这将忽略用户按下的所有键,直到他们按下Enter键为止,这与OP要求的完全不同。
乔纳森·哈特利

1
另外,如果您要使用“输入”,则捕获SyntaxError是不合适的。无论用户类型如何,都将得到评估,因此,例如,如果用户键入“ 1/0”,则将引发ZeroDivisionError而不是SyntaxError,并且程序将退出。
乔纳森·哈特利

如@Blorgbeard所述,只需使用raw_input(“按Enter键继续...”)就足够了。我现在经常在调试时使用它。
alltrue

15

python 手册提供以下内容:

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)

可以合并到您的用例中。


12
优良作法是复制您链接的内容,以便即使链接消失(而且确实如此),知识也仍然存在。
理查德

1
如何在Python 3.x中实现此目的?在3.x中,将print语句更改为兼容后,这将无限循环,并且不等待输入。不过,它在Python 2中效果很好。

链接已更新,可以重定向到其他页面。新的链接在这里。
马提亚斯(Matthias)'18

15

跨平台,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东西,因为它给了IOErrors,我不需要它。我之所以使用此代码,是因为我想阻止它。;)

附录:

我在PyPI上的一个包中实现了此功能,并使用了许多其他名为console的好东西:

>>> from console.utils import wait_key

>>> wait_key()
'h'

1
不适当的IOCTL设备”:我的错误
贝努瓦

@Benoit哪个操作系统?
Gringo Suave

14

我不知道这样做是与平台无关的,但是在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()返回所按下键的序数,以便使其具有与强制转换相同的输出。


使用诅咒比手册中描述的复杂例子要好得多,即使它涉及很大的依赖性。+1
达米安

4

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

sys.stdin.readline()

2
重点是用户不必仅按Enter键,例如只需敲一下空格键即可。如果您需要Enter来避免发生意外情况,那么这是错误的设计。
Synetech

3

我是python的新手,我已经认为自己太愚蠢了,无法重现这里提出的最简单的建议。事实证明,有一个陷阱应该知道:

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

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

因此,如果上面发布的任何代码都不适合您,请尝试手动运行脚本,而不要从IDLE运行


0

如果要查看他们是否按下了确切的键(例如说“ b”),请执行以下操作:

while True:
    choice = raw_input("> ")

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

8
这要求用户键入“ b”(或其他内容),然后按Enter键,这与OP要求的完全不同。
乔纳森·哈特利

0

os.system似乎总是调用sh,后者无法识别s和n选项以进行读取。但是,可以将read命令传递给bash:

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

2
阅读的文档使我认为,除非您指定-t选项,否则不会超时。
詹姆斯·金
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.