Я запускаю 64-битный Python 2.7.3 на Win7 64-bit. Я могу достоверно скрыть интерпретатор Python, выполнив следующее:
>>> from scipy import stats
>>> import time
>>> time.sleep(3)
и нажмите Control-C во время сна. KeyboardInterrupt не поднимается; переводчик терпит крах. Отпечатано следующее:
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.
Googling для "forrtl" и т.п., я вижу предложения, что такая проблема связана с использованием библиотеки Fortran, которая переопределяет обработку Ctrl-C. Я не вижу ошибки в Scipy trackerbut, учитывая, что Scipy - это библиотека для использования с Python, я считаю это ошибкой. Он прерывает обработку Python с помощью Ctrl-C. Есть ли обходной путь для этого?
Изменить: Следуя предложению @cgohlke, я попытался добавить свой собственный обработчик после импорта scipy. Этот вопрос о связанной проблеме показывает, что добавление обработчика сигнала не работает. Я попытался использовать функцию API SetConsoleCtrlHandler через 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 я am", но Python по-прежнему падает с ошибкой forrtl. Иногда я также получаю сообщение о том, что функция ConsoleCtrlHandler не удалась, что быстро исчезает.
Если я запустил это в IPython, я могу увидеть обычную трассировку Python KeyboardInterrupt перед ошибкой forrtl. Я также вижу обычную трассировку Python, за которой следует ошибка forrtl, если я вызываю другую ошибку вместо KeyboardInterrupt (например, ValueError):
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) и сам сбой. Есть ли способ устранить это?