我正在制作一个从键盘读取输入的算法,将其存储在名为 message 的变量上,然后将此变量写入文件。但是,每当用户输入时,如果他按下ESC键,我希望执行停止而没有任何错误。
我们说代码是:
message = raw_input()
我需要添加什么?所以,如果我在句子中间,如:
My name is th
我点击ESC,它会停止吗?
答案 0 :(得分:4)
正常输入无法做到这一点。 raw_input
一次读取整行。
在某些(极少数)情况下,您可以这样做:
message = ''
while True:
ch = sys.stdin.read(1)
if ch == '\x1b':
exit(0)
elif ch == '\n':
break
message += ch
但总的来说,这不起作用。例如,在典型的Unix系统上,sys.stdin
将进行行缓冲,甚至可能通过像readline
这样的库提供,以允许用户在进行编辑时进行编辑。或者,如果您在IDLE中运行程序,则根本无法读取stdin
; raw_input
通过弹出一个要求输入的对话框来解决这个问题,但是你的代码不能这样做。
您可以在不同情况下在不同平台上以不同方式解决这个问题。
在Windows上,如果您知道您的输入将是“DOS提示”窗口(可以使用sys.stdin.isatty()
检查),则可以使用msvcrt
功能。例如:
import sys, msvcrt
assert sys.stdin.isatty(), "Can't run without a console to run on"
message = u''
while True:
ch = msvcrt.getwche()
if ch == u'\x1b':
exit(0)
elif ch == u'\n':
break
message += ch
这适用于2.6+和3.3+,但在2.x中,与raw_input
不同,它会返回unicode
而不是str
。如果您想要str
,请删除所有u
前缀并使用getche
代替getwche
。
在大多数具有合理标准termios
(包括Mac OS X和Linux)的POSIX平台上,如果您知道您的输入将是“TTY”(可以使用{{3}查看) - 或者,如果您愿意,您可以只使用TTY来代替stdin,虽然这在很多平台上都不起作用/在很多情况下都是如此),您可以使用[termios
] (sys.stdin.isatty()
)或http://docs.python.org/3/library/termios.html模块将输入置于“原始”模式。在Python 3.x中,您可能必须直接从tty
而不是sys.stdin
读取,并手动解码为Unicode。所以:
import sys, termios, tty
assert sys.stdin.isatty(), "Can't run without a console to run on"
fd = sys.stdin.fileno()
stash = termios.tcgetattr(fd)
try:
tty.setraw(fd)
newterm = termios.tcgetattr(fd)
newterm[tty.LFLAG] |= termios.ECHO
termios.tcsetattr(fd)
message = b''
while True:
ch = sys.stdin.buffer.read(1)
if ch == b'\x1b':
exit(0)
elif ch == b'\n':
break
else:
message += ch
message = message.decode(sys.stdin.encoding)
finally:
termios.tcsetattr(fd, termios.TCSANOW, stash)
与Windows版本一样,这应该是2.6 + / 3.3 +多版本兼容,除了它始终返回unicode
而2.x raw_input
将返回{{1 (在这种情况下,所有这些都在str
行中,如果你不想要它,你可以删除它。)
请注意,我在这里同时使用了decode
和tty
。 termios
模块是更高级别的包装器,但它并不能完成您想要的任何操作。因此,您可以尽可能地使用它(在您的平台上翻转需要的任何开关以获得原始模式,并允许您使用跨平台/可读名称来表示标志集和值而不是索引),但是通常无论如何仍然需要tty
。
在任何其他平台上,你都是自己的。