是否有办法从用户输入中读取单个字符?例如,他们在终端上按下一个键,它就会返回(有点像getch())。我知道Windows中有这个功能,但我想要跨平台的东西。
当前回答
这是NON-BLOCKING,读取一个键并将其存储在keypress.key中。
import Tkinter as tk
class Keypress:
def __init__(self):
self.root = tk.Tk()
self.root.geometry('300x200')
self.root.bind('<KeyPress>', self.onKeyPress)
def onKeyPress(self, event):
self.key = event.char
def __eq__(self, other):
return self.key == other
def __str__(self):
return self.key
在你的程序中
keypress = Keypress()
while something:
do something
if keypress == 'c':
break
elif keypress == 'i':
print('info')
else:
print("i dont understand %s" % keypress)
其他回答
(目前)排名第一的答案(带有ActiveState代码)过于复杂。当仅仅一个函数就足够了时,我不认为有理由使用类。下面是两个实现,它们实现了相同的功能,但代码可读性更强。
这两个实现:
可以在python2或python3中正常工作 可以在Windows, OSX和Linux上工作 只读取一个字节(即,它们不等待换行符) 不要依赖任何外部库 是自包含的(没有函数定义之外的代码)
版本1:易读且简单
def getChar():
try:
# for Windows-based systems
import msvcrt # If successful, we are on Windows
return msvcrt.getch()
except ImportError:
# for POSIX-based systems (with termios & tty support)
import tty, sys, termios # raises ImportError if unsupported
fd = sys.stdin.fileno()
oldSettings = termios.tcgetattr(fd)
try:
tty.setcbreak(fd)
answer = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, oldSettings)
return answer
版本2:避免重复导入和异常处理:
[编辑]我错过了ActiveState代码的一个优点。如果您计划多次读取字符,该代码可以避免在类unix系统上重复Windows导入和ImportError异常处理的成本(可以忽略不计)。虽然你可能应该更关心代码的可读性,而不是可以忽略的优化,这里有一个替代方案(它类似于Louis的答案,但getChar()是自包含的),它的功能与ActiveState代码相同,更可读:
def getChar():
# figure out which function to use once, and store it in _func
if "_func" not in getChar.__dict__:
try:
# for Windows-based systems
import msvcrt # If successful, we are on Windows
getChar._func=msvcrt.getch
except ImportError:
# for POSIX-based systems (with termios & tty support)
import tty, sys, termios # raises ImportError if unsupported
def _ttyRead():
fd = sys.stdin.fileno()
oldSettings = termios.tcgetattr(fd)
try:
tty.setcbreak(fd)
answer = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, oldSettings)
return answer
getChar._func=_ttyRead
return getChar._func()
使用上述getChar()版本的示例代码:
from __future__ import print_function # put at top of file if using Python 2
# Example of a prompt for one character of input
promptStr = "Please give me a character:"
responseStr = "Thank you for giving me a '{}'."
print(promptStr, end="\n> ")
answer = getChar()
print("\n")
print(responseStr.format(answer))
内置的raw_input应该会有所帮助。
for i in range(3):
print ("So much work to do!")
k = raw_input("Press any key to continue...")
print ("Ok, back to work.")
另一种方法:
import os
import sys
import termios
import fcntl
def getch():
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)
break
except IOError: pass
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
return c
摘自这篇博文。
我对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())
值得一试的是readchar库,它在一定程度上基于其他答案中提到的ActiveState配方(但从那以后已经有了很长的路要走)。
安装:
python -m pip install readchar
用法:
import readchar
print('Reading a char:')
print(repr(readchar.readchar()))
print('Reading a key:')
print(repr(readchar.readkey()))
使用Python 3.9在Windows和Linux上测试。
Windows和Linux之间的键码并不总是相同的,但是库提供了特定于平台的定义,如readchar.key。F1来帮忙。
由于Linux将大多数特殊键报告为转义序列(从\x1b开始),如果您按下实际的转义键(终端将其报告为单独的\x1b), readkey()就会混淆。不幸的是,这是一个常见的Unix问题,没有真正可靠的解决方案。
注意,当readkey在Ctrl+C上触发KeyboardInterrupt时(参见readchar.config),其他Linux信号键(例如Ctrl+D和Ctrl+Z)被捕获并返回(分别为'\x04'和'\x1a'),这可能是也可能不是可取的。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用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中获得所有直接子目录