我在 Win7 64 位上运行 64 位 Python 2.7.3。我可以通过这样做可靠地使 Python 解释器崩溃:
>>> from scipy import stats
>>> import time
>>> time.sleep(3)
并在睡眠期间按 Control-C。不会引发键盘中断;解释器崩溃了。打印出以下内容:
forrtl: error (200): program aborting due to control-C event
Image PC Routine Line Source
libifcoremd.dll 00000000045031F8 Unknown Unknown Unknown
libifcoremd.dll 00000000044FC789 Unknown Unknown Unknown
libifcoremd.dll 00000000044E8583 Unknown Unknown Unknown
libifcoremd.dll 000000000445725D Unknown Unknown Unknown
libifcoremd.dll 00000000044672A6 Unknown Unknown Unknown
kernel32.dll 0000000077B74AF3 Unknown Unknown Unknown
kernel32.dll 0000000077B3F56D Unknown Unknown Unknown
ntdll.dll 0000000077C73281 Unknown Unknown Unknown
这使得无法中断长时间运行的 scipy 计算。
谷歌搜索“forrtl”等,我看到建议此类问题是由于使用覆盖 Ctrl-C 处理的 Fortran 库造成的。我没有在 Scipy 跟踪器上看到错误,但考虑到 Scipy 是一个与 Python 一起使用的库,我认为这是一个错误。它破坏了 Python 对 Ctrl-C 的处理。有什么解决方法吗?
编辑:按照 @cgohlke 的建议,我尝试在导入 scipy 后添加自己的处理程序。这个问题 https://gis.stackexchange.com/questions/2190/keyboardinterrupt-doesnt-work-when-arcgisscripting-module-is-loaded/2197#2197关于相关问题表明添加信号处理程序不起作用。我尝试使用 Windows API设置ConsoleCtrlHandler http://msdn.microsoft.com/en-us/library/windows/desktop/ms686016%28v=vs.85%29.aspx通过 pywin32 函数:
from scipy import stats
import win32api
def doSaneThing(sig, func=None):
print "Here I am"
raise KeyboardInterrupt
win32api.SetConsoleCtrlHandler(doSaneThing, 1)
之后,按 Ctrl-C 会打印“Here I am”,但 Python 仍然因 forrtl 错误而崩溃。有时我还会收到一条消息“ConsoleCtrlHandler function failed”,但很快就消失了。
如果我在 IPython 中运行它,我可以在 forrtl 错误之前看到正常的 Python KeyboardInterrupt 回溯。如果我引发一些其他错误而不是 KeyboardInterrupt(例如 ValueError),我还会看到正常的 Python 回溯,后跟 forrtl 错误:
ValueError Traceback (most recent call last)
<ipython-input-1-08defde66fcb> in doSaneThing(sig, func)
3 def doSaneThing(sig, func=None):
4 print "Here I am"
----> 5 raise ValueError
6 win32api.SetConsoleCtrlHandler(doSaneThing, 1)
ValueError:
forrtl: error (200): program aborting due to control-C event
[etc.]
看起来无论底层处理程序在做什么,它不仅仅是直接捕获 Ctrl-C,而是对错误条件 (ValueError) 做出反应并导致自身崩溃。有什么办法可以消除这种情况吗?