我正在制作一个从键盘读取输入的算法,将其存储在一个名为message的变量中,然后将此变量写入文件中。但是,每当用户键入时,如果他们点击Esc,我希望执行停止而没有任何错误。
假设代码是:
message = raw_input()
我要补充什么?所以如果我在一个句子的中间,比如:
My name is th
我打了Esc,它停止了吗?
普通输入无法做到这一点。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是,它返回 aunicode而不是 a str。如果你想str在这里,删除所有u前缀并使用getche而不是getwche.
在大多数具有合理标准的类似 POSIX 的平台上termios(包括 Mac OS X 和 Linux),如果您知道您的输入将是“TTY”(您可以使用它进行检查sys.stdin.isatty()- 或者,如果您愿意,您可以只寻找一个 TTY 来代替标准输入,虽然这在很多平台上/在很多情况下都不起作用),您可以使用[termios]( http://docs.python.org/3/library/termios.html ) 或tty模块将输入置于“原始”模式。在 Python 3.x 中,您可能必须直接从sys.stdin.buffer而不是读取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.xraw_input会返回str(在这种情况下,它都在这一decode行中,你可以删除它)如果你不想要它)。
请注意,我使用了两者tty和termios这里。该tty模块是一个更高级别的包装器,但它并不能满足您的所有需求。因此,您可以尽可能地使用它(翻转在您的平台上获取原始模式所需的任何开关,并让您对标志集和值使用跨平台/可读名称而不是索引),但您通常termios反正还是需要的。
在任何其他平台上,您都是靠自己的。