简体   繁体   English

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

[英]raw_input() and sys.stdin misbehaves on CTRL-C

I am trying to detect a KeyboardInterrupt exception when CTRL-C is pressed during a raw_input() prompt. 我在raw_input()提示符期间按下CTRL-C时尝试检测KeyboardInterrupt异常。 Normally the following code works just fine to detect the command: 通常,以下代码可以正常检测命令:

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

The problem comes when trying to intercept the input from sys.stdin. 尝试拦截sys.stdin的输入时出现问题。 After adding some code in between raw_input() and sys.stdin, the CTRL-C command now results in two exceptions: EOFError followed by KeyboardInterrupt a line or two later. 在raw_input()和sys.stdin之间添加一些代码之后,CTRL-C命令现在导致两个例外:EOFError后面跟随KeyboardInterrupt一行或两行。 This is the code used to test: 这是用于测试的代码:

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())

Which results in the following being printed out: 这导致打印出以下内容:

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

Am I missing something obvious? 我错过了一些明显的东西吗 Maybe intercepting the input in a bad way? 也许以不好的方式拦截输入?

Found this fairly old page which seems like the same issue. 找到这个相当老的页面,看起来像是同一个问题。 No solution though: https://mail.python.org/pipermail/python-list/2009-October/555375.html 但是没有解决方案: https//mail.python.org/pipermail/python-list/2009-October/555375.html

Some environment details: Python 2.7.3 (64-bit), Windows 7 SP1 (64-bit) 一些环境细节:Python 2.7.3(64位),Windows 7 SP1(64位)

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

EDIT: An update to the readline method of StdinReplacement fixed the issue. 编辑: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'

It seems like the problem is that your readline method returns an empty line, thus signaling the end of file: 似乎问题是你的readline方法返回一个空行,从而发出文件结束的信号:

import sys

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

sys.stdin = Test()

raw_input('')   # EOFError!

However modifying it such that it doesn't return an empty line makes the code work: 但是,修改它以使它不返回空行使代码工作:

import sys

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

sys.stdin = Test()

raw_input('')   # no error

The readline method should return an empty string only when the file finished. readline方法应该在文件结束时返回一个空字符串。 The EOFError is used to mean exactly this: raw_input expected the file to contain a line, but the file ended. EOFError用于表示这一点: raw_input期望文件包含一行,但文件结束。


This is due to the call to PyFile_GetLine found at the end of the implementation of raw_input : 这是因为在raw_input的实现结束时调用了PyFile_GetLine

return PyFile_GetLine(fin, -1);

According to the documentation of PyFile_GetLine(PyObject *p, int n) : 根据PyFile_GetLine(PyObject *p, int n)的文档:

If n is less than 0 , however, one line is read regardless of length, but EOFError is raised if the end of the file is reached immediately. 但是,如果n小于0 ,则无论长度如何都会读取一行,但如果立即到达文件末尾,则会EOFError

Since it passes -1 as n the EOFError is raised when the EOF is found (ie you return an empty string from readline ). 由于它将-1作为n传递,因此在找到EOF时会EOFError (即从readline返回一个空字符串)。


As far as I can tell the behaviour you see is only possible if you insert the input and also create an interrupt. 据我所知,只有在插入输入并创建中断时才能看到行为。 Pressing only Ctrl + C doesn't generate any EOFError (at least on linux). 按Ctrl + C不会生成任何EOFError (至少在Linux上)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM