是否有办法从用户输入中读取单个字符?例如,他们在终端上按下一个键,它就会返回(有点像getch())。我知道Windows中有这个功能,但我想要跨平台的东西。
当前回答
我对python3的解决方案,不依赖于任何pip包。
# precondition: import tty, sys
def query_yes_no(question, default=True):
"""
Ask the user a yes/no question.
Returns immediately upon reading one-char answer.
Accepts multiple language characters for yes/no.
"""
if not sys.stdin.isatty():
return default
if default:
prompt = "[Y/n]?"
other_answers = "n"
else:
prompt = "[y/N]?"
other_answers = "yjosiá"
print(question,prompt,flush= True,end=" ")
oldttysettings = tty.tcgetattr(sys.stdin.fileno())
try:
tty.setraw(sys.stdin.fileno())
return not sys.stdin.read(1).lower() in other_answers
except:
return default
finally:
tty.tcsetattr(sys.stdin.fileno(), tty.TCSADRAIN , oldttysettings)
sys.stdout.write("\r\n")
tty.tcdrain(sys.stdin.fileno())
其他回答
用pygame试试这个:
import pygame
pygame.init() // eliminate error, pygame.error: video system not initialized
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
d = "space key"
print "You pressed the", d, "."
我相信这是一个最优雅的解决方案。
import os
if os.name == 'nt':
import msvcrt
def getch():
return msvcrt.getch().decode()
else:
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
def getch():
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
然后在代码中使用它:
if getch() == chr(ESC_ASCII_VALUE):
print("ESC!")
这里回答:python中的raw_input,不按enter
使用这个代码-
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()
参考:https://github.com/unfor19/mg-tools/blob/master/mgtools/get_key_pressed.py
接受的答案对我来说并不是那么好(我按住一个键,什么都不会发生,然后我按下另一个键,它就会工作)。
在学习了curses模块之后,这似乎是正确的方法。现在它可以通过Windows -游标(通过pip可用)用于Windows,因此您可以以与平台无关的方式进行编程。下面这个例子是受YouTube上这个教程的启发:
import curses
def getkey(stdscr):
curses.curs_set(0)
while True:
key = stdscr.getch()
if key != -1:
break
return key
if __name__ == "__main__":
print(curses.wrapper(getkey))
以.py扩展名保存,或在交互模式下运行curses.wrapper(getkey)。
TL;DR:这是你的无依赖跨平台最大密度复制面糊
我知道我一直在找☝️。你从谷歌来到这里,想要一些不需要pip安装这个和那个就能工作的东西?我相当肯定这个解决方案将继续工作很长一段时间。
示例使用
>>> getch_but_it_actually_works() # just normal key like a
'a'
>>> getch_but_it_actually_works() # a but its shift or capslock
'A'
>>> getch_but_it_actually_works() # just bare enter
'\r'
>>> getch_but_it_actually_works() # literal ESC key
'\x1b'
>>> getch_but_it_actually_works() # one of the arrow keys on linux
'\x1b[A'
>>> getch_but_it_actually_works() # one of the arrow keys on windows
'àK'
>>> getch_but_it_actually_works() # some really obscure key-combo. still works.
'\x1b[19;6~'
跨平台解决方案,无外部依赖
滚动到更详细的答案在结束理智的缩进和评论。这是最大密度预览,便于复制粘贴。只需调用getch_but_it_actually_works()
import os
def _read_one_wide_char_win(): return msvcrt.getwch()
def _char_can_be_escape_win(char): return True if char in ("\x00", "à") else False
def _dump_keyboard_buff_win():
try: msvcrt.ungetwch("a")
except OSError: return msvcrt.getwch()
else: _ = msvcrt.getwch(); return ""
def _read_one_wide_char_nix():
old_settings = termios.tcgetattr(sys.stdin.fileno()); tty.setraw(sys.stdin.fileno())
wchar = sys.stdin.read(1)
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, old_settings); return wchar
def _char_can_be_escape_nix(char): return True if char == "\x1b" else False
def _dump_keyboard_buff_nix():
old_settings = termios.tcgetattr(sys.stdin.fileno())
tty.setraw(sys.stdin.fileno()); os.set_blocking(sys.stdin.fileno(), False)
buffer_dump = ""
while char := sys.stdin.read(1): buffer_dump += char
os.set_blocking(sys.stdin.fileno(), True); termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, old_settings)
if buffer_dump: return buffer_dump
else: return ""
if os.name == "nt":
import msvcrt
read_one_wdchar, char_can_escape, dump_key_buffer = _read_one_wide_char_win, _char_can_be_escape_win, _dump_keyboard_buff_win
if os.name == "posix":
import termios, tty, sys
read_one_wdchar, char_can_escape, dump_key_buffer = _read_one_wide_char_nix, _char_can_be_escape_nix, _dump_keyboard_buff_nix
def getch_but_it_actually_works():
wchar = read_one_wdchar()
if char_can_escape(wchar): dump = dump_key_buffer(); return wchar + dump
else: return wchar
答案很长,代码带有注释和合理的缩进
这里是所有评论的长答案。仍然没有依赖关系。
这很可能在linux和windows上工作很长一段时间。没有外部依赖,只有内置。
它还将处理边缘情况,如敲击方向键或一些模糊的东西,如<ctrl + shift + f12>,这将在linux和windows上产生很长的ANSI转义序列。它将捕获诸如<ctrl+x>或<ctrl+z>或tab或F1-12作为单个输入
这些年来,我已经回到这个帖子上几十次了,所以现在是时候把两分钱和利息还给我了。下面是完整的注释代码。
这个例子有点长,但您可以跳过阅读大部分内容。相关的位在最后,你可以复制粘贴整个东西。
import os
def _read_one_wide_char_win():
"""Wait keyhit return chr. Get only 1st chr if multipart key like arrow"""
return msvcrt.getwch()
def _char_can_be_escape_win(char):
"""Return true if char could start a multipart key code (e.g.: arrows)"""
return True if char in ("\x00", "à") else False # \x00 is null character
def _dump_keyboard_buff_win():
"""If piece of multipart keycode in buffer, return it. Else return None"""
try: # msvcrt.kbhit wont work with msvcrt.getwch
msvcrt.ungetwch("a") # check buffer status by ungetching wchr
except OSError: # ungetch fails > something in buffer so >
return msvcrt.getwch() # return the buffer note: win multipart keys
else: # are always 2 parts. if ungetwch does not fail
_ = msvcrt.getwch() # clean up and return empty string
return ""
def _read_one_wide_char_nix():
"""Wait keyhit return chr. Get only 1st chr if multipart key like arrow"""
old_settings = termios.tcgetattr(sys.stdin.fileno()) # save settings
tty.setraw(sys.stdin.fileno()) # set raw mode to catch raw key w/o enter
wchar = sys.stdin.read(1)
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, old_settings)
return wchar
def _char_can_be_escape_nix(char):
"""Return true if char could start a multipart key code (e.g.: arrows)"""
return True if char == "\x1b" else False # "\x1b" is literal esc-key
def _dump_keyboard_buff_nix():
"""If parts of multipart keycode in buffer, return them. Otherwise None"""
old_settings = termios.tcgetattr(sys.stdin.fileno()) # save settings
tty.setraw(sys.stdin.fileno()) # raw to read single key w/o enter
os.set_blocking(sys.stdin.fileno(), False) # dont block for empty buffer
buffer_dump = ""
while char := sys.stdin.read(1):
buffer_dump += char
os.set_blocking(sys.stdin.fileno(), True) # restore normal settings
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, old_settings)
if buffer_dump:
return buffer_dump
else:
return ""
if os.name == "nt":
import msvcrt
read_one_wdchar = _read_one_wide_char_win
char_can_escape = _char_can_be_escape_win
dump_key_buffer = _dump_keyboard_buff_win
if os.name == "posix":
import termios
import tty
import sys
read_one_wdchar = _read_one_wide_char_nix
char_can_escape = _char_can_be_escape_nix
dump_key_buffer = _dump_keyboard_buff_nix
def getch_but_it_actually_works():
"""Returns a printable character or a keycode corresponding to special key
like arrow or insert. Compatible with windows and linux, no external libs
except for builtins. Uses different builtins for windows and linux.
This function is more accurately called:
"get_wide_character_or_keycode_if_the_key_was_nonprintable()"
e.g.:
* returns "e" if e was pressed
* returns "E" if shift or capslock was on
* returns "x1b[19;6~'" for ctrl + shift + F8 on unix
You can use string.isprintable() if you need to sometimes print the output
and sometimes use it for menu control and such. Printing raw ansi escape
codes can cause your terminal to do things like move cursor three rows up.
Enter will return "\ r" on all platforms (without the space seen here)
as the enter key will produce carriage return, but windows and linux
interpret it differently in different contexts on higher level
"""
wchar = read_one_wdchar() # get first char from key press or key combo
if char_can_escape(wchar): # if char is escapecode, more may be waiting
dump = dump_key_buffer() # dump buffer to check if more were waiting.
return wchar + dump # return escape+buffer. buff could be just ""
else: # if buffer was empty then we return a single
return wchar # key like "e" or "\x1b" for the ESC button
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录