CTRL-C上的raw_input()和sys.stdin行为不正常

时间:2014-07-14 12:35:53

标签: python exception raw-input

我在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'

1 个答案:

答案 0 :(得分:1)

似乎问题是你的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期望文件包含一行,但文件已结束。


这是由于end of the implementation of raw_input上的PyFile_GetLine来电:

return PyFile_GetLine(fin, -1);

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

  

如果n小于0,则无论长度如何,都会读取一行,   但如果立即到达文件末尾,则会引发EOFError

由于-1传递nEOFError会在找到EOF时被提升(即您从readline返回一个空字符串)。< / p>


据我所知,只有在插入输入并创建中断时才能看到行为。仅按 Ctrl + C 不会生成任何EOFError(至少在Linux上)。