点击ESC时立即进行python退出程序

时间:2013-10-24 00:24:27

标签: python pypy

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

我们说代码是:

message = raw_input()

我需要添加什么?所以,如果我在句子中间,如:

My name is th

我点击ESC,它会停止吗?

1 个答案:

答案 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行中,如果你不想要它,你可以删除它。)

请注意,我在这里同时使用了decodettytermios模块是更高级别的包装器,但它并不能完成您想要的任何操作。因此,您可以尽可能地使用它(在您的平台上翻转需要的任何开关以获得原始模式,并允许您使用跨平台/可读名称来表示标志集和值而不是索引),但是通常无论如何仍然需要tty


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