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

crd*_*vis 6 python exception raw-input

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

try:
    input = raw_input("Input something: ")
except KeyboardInterrupt:
    do_something()
Run Code Online (Sandbox Code Playgroud)

尝试拦截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())
Run Code Online (Sandbox Code Playgroud)

这导致打印出以下内容:

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
Run Code Online (Sandbox Code Playgroud)

我错过了一些明显的东西吗 也许以不好的方式拦截输入?

找到这个相当老的页面,看起来像是同一个问题.但是没有解决方案: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'
Run Code Online (Sandbox Code Playgroud)

Bak*_*riu 1

问题似乎是您的readline方法返回一个空行,从而表明文件结束:

import sys

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

sys.stdin = Test()

raw_input('')   # EOFError!
Run Code Online (Sandbox Code Playgroud)

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

import sys

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

sys.stdin = Test()

raw_input('')   # no error
Run Code Online (Sandbox Code Playgroud)

当文件完成时,该readline方法才应返回空字符串。的确切含义是:预期文件包含一行,但文件结束了。EOFErrorraw_input


这是由于PyFile_GetLine执行结束时raw_input调用了 find :

return PyFile_GetLine(fin, -1);
Run Code Online (Sandbox Code Playgroud)

根据以下文件PyFile_GetLine(PyObject *p, int n)

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

因为当找到 时,它会-1被引发(即,您从 中返回一个空字符串)。nEOFErrorEOFreadline


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