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 中按下回车键。有没有办法从用户输入中完成我需要的操作,而无需在 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)
其工作原理是在从终端读取之前将终端置于非规范输入模式。
不回显用户输入的替代解决方案(例如,如果用户按下z
,z
则不会出现在屏幕上):
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
。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件