windows - 为什么我不能处理 KeyboardInterrupt python?

我正在为Windows编写python 2.6.6代码,如下所示:


try:
 dostuff()
except KeyboardInterrupt:
 print"Interrupted!"
except:
 print"Some other exception?"
finally:
 print"cleaning up...."
 print"done."

dostuff()是一个永久循环的函数,一次从输入流读取一行并在其中执行操作,我希望当按下ctrl键时能够停止它,清除它。

相反,except KeyboardInterrupt:下面的代码根本没有运行,打印的唯一内容是"cleaning up...",然后打印一个类似于下面这样的回溯:


Traceback (most recent call last):
 File"filename.py", line 119, in <module>
 print 'cleaning up...'
KeyboardInterrupt

因此,异常处理代码未运行,并且回溯声称在finally子句中发生了KeyboardInterrupt,这没有意义,因为按ctrl-c是导致该部分运行的原因!即使是通用except:子句也没有运行。

我用sys.stdin.read()替换了try:块的内容,这个问题仍然按照描述的方式发生,第一行正在运行,然后打印相同的回溯。

因此,这将失败:


try:
 sys.stdin.read()
except KeyboardInterrupt:
 ...

但这是有效的:


try:
 sys.stdin.read()
 print"Done reading."
except KeyboardInterrupt:
 ...

以下是打印的内容:


Done reading. Interrupted!
cleaning up...
done.

由于某些原因,即使在上一行发生异常,也会打印"Done reading.",即使上一行发生异常。这不是真正的问题-显然我必须能够在"try"块内的地方处理异常,

我觉得,这是在阻塞系统调用期间处理中断的错误。

时间:

sys.stdin.read()是一个系统调用,因此每个系统的行为都会有所不同,对于Windows 7,我认为正在进行的输入是缓冲的,所以sys.stdin.read()将把所有内容返回到ctrl c,然后再次访问sys.stdin 。

请尝试以下操作:


def foo():
 try:
 print sys.stdin.read()
 print sys.stdin.closed
 except KeyboardInterrupt:
 print"Interrupted!"

这表明正在进行stdin的缓冲,这导致另一个对stdin的调用来识别键盘输入


def foo():
 try:
 x=0
 while 1:
 x += 1
 print x
 except KeyboardInterrupt:
 print"Interrupted!"

似乎没有什么问题。

我有类似的问题,这是解决方法:


try:
 some_blocking_io_here() # CTRL-C to interrupt
except:
 try:
 print() # any i/o will get the second KeyboardInterrupt here?
 except:
 real_handler_here()

下面是有关发生的情况的猜测:

  • 按Ctrl-C中断"打印"语句( 出于任何原因。) 。 BugWin32限制)?
  • 按Ctrl-C也会引发第一个 KeyboardInterrupt,在 dostuff ( ) 中
  • 异常处理程序运行并尝试打印"已经中断",但"打印"语句已损坏并引发另一个 KeyboardInterrupt 。
  • finally子句运行并尝试打印"正在清理。",但"打印"语句被破坏并引发了另一个 KeyboardInterrupt 。

在我这里可以工作:


import sys

if __name__ =="__main__":
 try:
 sys.stdin.read()
 print"Here"
 except KeyboardInterrupt:
 print"Worked"
 except:
 print"Something else"
 finally:
 print"Finally"

尝试在dostuff()函数之外放置一行,或者将循环条件移到函数之外,例如:


try:
 while True:
 dostuff()
except KeyboardInterrupt:
 print"Interrupted!"
except:
 print"Some other exception?"
finally:
 print"cleaning up...."
 print"done."

...