input()和sys.stdin在CTRL上行为不当

我正在尝试在raw_input()提示符期间按CTRL-C时检测到KeyboardInterrupt异常。 通常,以下代码可以很好地检测命令:

try:
    input = raw_input("Input something: ")
except KeyboardInterrupt:
    do_something()

尝试拦截来自sys.stdin的输入时出现问题。 在raw_input()和sys.stdin之间添加一些代码之后,CTRL-C命令现在会导致两个例外:EOFError,后跟KeyboardInterrupt后面的一行或两行。 这是用于测试的代码:

import sys
import traceback

class StdinReplacement(object):
    def __init__(self):
        self.stdin = sys.stdin
        sys.stdin = self
    def readline(self):
        input = self.stdin.readline()
        # here something could be done with input before returning it
        return input

if __name__ == '__main__':

    rep = StdinReplacement()
    while True:
        info = None
        try:
            try:
                input = raw_input("Input something: ")
                print input
            except:
                info = sys.exc_info()
                print info
        except:
            print 'n'
            print "0:", traceback.print_traceback(*info)
            print "1:", traceback.print_exception(*sys.exc_info())

这会导致以下内容被打印出来:

0:Traceback (most recent call last):
  File "stdin_issues.py", line 19, in <module>
    input = raw_input("Input something: ")
EOFError: EOF when reading a line
 None
1:Traceback (most recent call last):
  File "stdin_issues.py", line 23, in <module>
    print info
KeyboardInterrupt

我错过了明显的东西吗? 可能以不好的方式拦截输入?

发现这个相当古老的页面,看起来像是同一个问题。 尽管没有解决方案:https://mail.python.org/pipermail/python-list/2009-October/555375.html

一些环境细节:Python 2.7.3(64位),Windows 7 SP1(64位)

-------------------------------------------------- ----------------------

编辑:对StdinReplacement的readline方法的更新修复了这个问题。

def readline(self):
    input = self.stdin.readline()
    # here something could be done with input before returning it
    if len(input) > 0:
        return input
    else:
        return 'n'

看来问题在于你的readline方法返回一个空行,从而表示文件结束:

import sys

class Test(object):
    def readline(self):
        return ''

sys.stdin = Test()

raw_input('')   # EOFError!

但是修改它以使其不返回空行将使代码正常工作:

import sys

class Test(object):
    def readline(self):
        return 'n'  # or 'a', or whatever

sys.stdin = Test()

raw_input('')   # no error

只有当文件完成时, readline方法才会返回一个空字符串。 EOFError用于表示这一点: raw_input预期文件包含一行,但文件结束。


这是由于调用了在raw_input实现结束时发现的PyFile_GetLine

return PyFile_GetLine(fin, -1);

根据PyFile_GetLine(PyObject *p, int n)的文档:

但是,如果n小于0 ,则不管长度如何都会读取一行,但如果立即到达文件末尾,则会EOFError

由于它将n作为n传递-1 ,因此发现EOF时会EOFError (即,您从readline返回一个空字符串)。


据我所知,只有在插入输入并创建中断的情况下才能看到行为。 只按Ctrl + C不会产生任何EOFError (至少在linux上)。

链接地址: http://www.djcxy.com/p/9657.html

上一篇: input() and sys.stdin misbehaves on CTRL

下一篇: server script hangs until I press [enter]