有没有办法做到这一点与正常输入。 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”(你可以用sys.stdin.isatty() -or检查,如果你愿意的话,你可以找一个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.X raw_input将返回str(在此大小写全部在decode行中,如果不需要,可以放弃)。

请注意,我在这里同时使用了tty和termios。 tty模块是一个更高级别的包装,但它不会做你想做的一切。因此,您可以尽可能使用它(翻转需要的任何开关以在您的平台上获取原始模式,并让您为标记集和值使用跨平台/可读名称而不是索引),但通常无论如何还是需要termios。

在任何其他平台上,你是自己的。