我正在制作一个从键盘读取输入的算法,将其存储在一个名为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
反正还是需要的。
在任何其他平台上,您都是靠自己的。