如何让python等待按下的键?

问题:如何让python等待按下的键?

我希望我的脚本等待用户按下任何键。

我怎么做?

I want my script to wait until the user presses any key.

How do I do that?


回答 0

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))

In Python 3 use input():

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

In Python 2 use raw_input():

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

This only waits for the user to press enter though.

One might want to use msvcrt ((Windows/DOS only) The msvcrt module gives you access to a number of functions in the Microsoft Visual C/C++ Runtime Library (MSVCRT)):

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

This should wait for a key press.

Additional info:

in Python 3 raw_input() does not exist

In Python 2 input(prompt) is equivalent to eval(raw_input(prompt))


回答 1

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

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

在python3中 input()

One way to do this in Python 2, is to use raw_input():

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

In python3 it’s just input()


回答 2

在我的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)

On my linux box, I use the following code. This is similar to code I’ve seen elsewhere (in the old python FAQs for instance) but that code spins in a tight loop where this code doesn’t and there are lots of odd corner cases that code doesn’t account for that this code does.

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

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

Linux:

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

视窗:

import os
os.system("pause")

If you are ok with depending on system commands you can use the following:

Linux:

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

Windows:

import os
os.system("pause")

回答 4

只需使用

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

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

简单修复方法:

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

Simply using

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

will cause a SyntaxError: expected EOF while parsing.

Simple fix use:

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

回答 5

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)

可以合并到您的用例中。

The python manual provides the following:

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)

which can be rolled into your use case.


回答 6

跨平台,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'

Cross Platform, Python 2/3 code:

# 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

I removed the fctl/non-blocking stuff because it was giving IOErrors and I didn’t need it. I’m using this code specifically because I want it to block. ;)

Addendum:

I implemented this in a package on PyPI with a lot of other goodies called console:

>>> from console.utils import wait_key

>>> wait_key()
'h'

回答 7

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

I don’t know of a platform independent way of doing it, but under Windows, if you use the msvcrt module, you can use its getch function:

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

mscvcrt also includes the non-blocking kbhit() function to see if a key was pressed without waiting (not sure if there’s a corresponding curses function). Under UNIX, there is the curses package, but not sure if you can use it without using it for all of the screen output. This code works under UNIX:

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

Note that curses.getch() returns the ordinal of the key pressed so to make it have the same output I had to cast it.


回答 8

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

sys.stdin.readline()

If you want to wait for enter (so the user knocking the keyboard does not cause something un-intended to happen) use

sys.stdin.readline()

回答 9

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

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

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

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

I am new to python and I was already thinking I am too stupid to reproduce the simplest suggestions made here. It turns out, there’s a pitfall one should know:

When a python-script is executed from IDLE, some IO-commands seem to behave completely different (as there is actually no terminal window).

Eg. msvcrt.getch is non-blocking and always returns $ff. This has already been reported long ago (see e.g. https://bugs.python.org/issue9290 ) – and it’s marked as fixed, somehow the problem seems to persist in current versions of python/IDLE.

So if any of the code posted above doesn’t work for you, try running the script manually, and NOT from IDLE.


回答 10

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

while True:
    choice = raw_input("> ")

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

If you want to see if they pressed a exact key (like say ‘b’) Do this:

while True:
    choice = raw_input("> ")

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

回答 11

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

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

os.system seems to always invoke sh, which does not recognize the s and n options for read. However the read command can be passed to bash:

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