我如何等待按下的按键?
- 2024-12-23 08:43:00
- admin 原创
- 109
问题描述:
如何让我的 Python 脚本等待直到用户按下任意键?
解决方案 1:
在Python 3中,使用input()
:
input("Press Enter to continue...")
在Python 2中,使用raw_input()
:
raw_input("Press Enter to continue...")
但这仅等待用户按下回车键。
在 Windows/DOS 上,可能需要使用msvcrt
。该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))
。
解决方案 2:
在 Python 3 中,使用input()
:
input("Press Enter to continue...")
在 Python 2 中,使用raw_input()
:
raw_input("Press Enter to continue...")
解决方案 3:
在我的 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)
解决方案 4:
如果您不介意依赖系统命令,您可以使用:
from __future__ import print_function
import os
import platform
if platform.system() == "Windows":
os.system("pause")
else:
os.system("/bin/bash -c 'read -s -n 1 -p \"Press any key to continue...\"'")
print()
它已经过验证可以在 Windows、Linux 和 Mac OS X 上与 Python 2 和 3 兼容。
解决方案 5:
只需使用
input("Press Enter to continue...")
使用Python2时会出现以下错误:
语法错误:解析时预期出现 EOF。
使代码在 Python 2 和 Python 3 上都能运行的简单修复方法是使用:
try:
input("Press enter to continue")
except SyntaxError:
pass
解决方案 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.getwch()
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
s 而我不需要它。我使用这个代码是因为我希望它阻塞。;)
附录:
我在 PyPI 上的一个包中实现了这个功能,其中还有许多其他名为console 的好东西:
>>> from console.utils import wait_key
>>> wait_key()
'h'
解决方案 7:
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)
可以将其纳入到您的用例中。
解决方案 8:
我不知道是否有一种独立于平台的方法,但在 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()
返回所按下键的序数,因此为了使其具有相同的输出,我必须对其进行转换。
解决方案 9:
我是 Python 新手,我已经认为自己太笨了,无法重现这里最简单的建议。事实证明,有一个陷阱需要知道:
当从 IDLE 执行 python 脚本时,某些 IO 命令似乎表现得完全不同(因为实际上没有终端窗口)。
例如,msvcrt.getch 是非阻塞的,并且始终返回 $ff。这个问题很久以前就被报告过了(例如参见https://bugs.python.org/issue9290)——并且被标记为已修复,但不知何故,这个问题似乎仍然存在于当前版本的 python/IDLE 中。
因此,如果上面发布的任何代码对您不起作用,请尝试手动运行脚本,而不是从 IDLE 运行。
解决方案 10:
您可以使用键盘库:
import keyboard
keyboard.wait('space')
print('space was pressed, continuing...')
解决方案 11:
如果你想等待输入(这样用户敲击键盘不会导致意外的事情发生)使用
sys.stdin.readline()
解决方案 12:
os.system
似乎总是调用sh
,它无法识别 read 的 s 和 n 选项。但是 read 命令可以传递给 bash:
os.system("""bash -c 'read -s -n 1 -p "Press any key to continue..."'""")
解决方案 13:
如果您想查看他们是否按下了某个精确的键(比如说“b”),请执行以下操作:
while True:
choice = raw_input("> ")
if choice == 'b' :
print "You win"
input("yay")
break
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)