0

我正在制作一个从键盘读取输入的算法,将其存储在一个名为message的变量中,然后将此变量写入文件中。但是,每当用户键入时,如果他们点击Esc,我希望执行停止而没有任何错误。

假设代码是:

message = raw_input()

我要补充什么?所以如果我在一个句子的中间,比如:

My name is th

我打了Esc,它停止了吗?

4

1 回答 1

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 中运行程序,则根本无法读取stdinraw_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行中,你可以删除它)如果你不想要它)。

请注意,我使用了两者ttytermios这里。该tty模块是一个更高级别的包装器,但它并不能满足您的所有需求。因此,您可以尽可能地使用它(翻转在您的平台上获取原始模式所需的任何开关,并让您对标志集和值使用跨平台/可读名称而不是索引),但您通常termios反正还是需要的。


在任何其他平台上,您都是靠自己的。

于 2013-10-24T00:33:19.540 回答