Eclipse + Pydev: функции очистки не вызываются при нажатии кнопки «Стоп»?

Попытка запустить этот файл в eclipse

class Try:
   def __init__(self):
       pass
   def __del__(self):
       print 1
a=Try()
raw_input('waiting to finish')

и нажатие кнопки остановки без завершения программы не печатает «1», т.е. метод del никогда не вызывается. Если я попытаюсь запустить скрипт из оболочки и выполню ctrl-c\sys.exit, "1" будет напечатано, т.е. вызывается del. То же самое, если я попытаюсь использовать wait():

class A:

    def __enter__(self):
        return None
    def __exit__(self, type, value, traceback):
        print 3


with A():
    print 1
    raw_input('Waiting')
    print 2

Если я нажму «стоп» при появлении запроса, «3» не будет напечатано

Почему это? Есть ли способ обойти это?

Спасибо, Ноам


person olamundo    schedule 11.08.2009    source источник


Ответы (2)


Нажатие stop в Eclipse сразу убивает интерпретатор (хотя на самом деле он довольно часто дает сбой). Как и при использовании kill/taskkill, процесс не знает о своей кончине.

Фрагмент Ctrl+C из Википедии...

Control-C как команда прерывания была популяризирована UNIX и принята в других системах. В системах POSIX последовательность заставляет активную программу получать сигнал SIGINT. Если программа не указывает, как обрабатывать это условие, она завершается. Обычно программа, которая обрабатывает SIGINT, все равно завершает себя или, по крайней мере, завершает выполнение задачи внутри нее.

Ctrl+C — это управляющий сигнал для прерывания программы, но, как вы могли заметить в середине этого абзаца, программы могут указывать, как обрабатывать этот сигнал. В Python сочетание клавиш Ctrl+C выдает исключение KeyboardInterrupt, которое обычно перехватывается, а затем Python выходит чисто. Даже если вы убиваете интерпретатор с помощью Ctrl+C, он может справиться с этим, чтобы очистить среду перед выходом.

Я включил следующее, потому что вы спросили: «Есть ли способ обойти это?»

Если вы хотите остановить вызовы raw_input(...), вы можете использовать Ctrl+Z для отправки EOF. Я осмотрелся, и, к сожалению, нет возможности отправить Ctrl+C/0x03 в Eclipse.

person Zwergner    schedule 11.08.2009
comment
Спасибо, но я думаю, что вы не ответили на мой вопрос - при запуске из оболочки остановка интерпретатора с помощью ctrl-c все равно вызывает del, но при остановке в eclipse этого не происходит. Я не ищу решения, просто интересно, в чем причина разницы - person olamundo; 11.08.2009
comment
Я немного ошибся или, по крайней мере, плохо объяснил, поэтому немного подчистил и добавил больше информации. - person Zwergner; 12.08.2009
comment
ОК, спасибо - Ваш ответ точен. Сначала я этого не понял. Извиняюсь - person olamundo; 13.08.2009

Документы Python:

__del__(self)

Вызывается, когда экземпляр собирается быть уничтоженным. Это также называется деструктором. Если базовый класс имеет метод __del__(), метод __del__() производного класса, если таковой имеется, должен явно вызвать его, чтобы обеспечить надлежащее удаление части экземпляра базового класса. Обратите внимание, что для метода __del__() возможно (хотя и не рекомендуется!) отложить уничтожение экземпляра, создав новую ссылку на него. Затем он может быть вызван позже, когда эта новая ссылка будет удалена. Не гарантируется вызов __del__() методов для объектов, которые все еще существуют при выходе из интерпретатора.

Если вы хотите гарантировать вызов метода, используйте with-statement

person Jochen Ritzel    schedule 11.08.2009
comment
Может быть, я что-то упускаю, но я не уверен, что это правильно для моего случая: у меня есть класс A, который содержит экземпляр класса B, а B содержит некоторый внешний ресурс, который он должен явно освобождать при выходе. Как я могу решить эту проблему, используя with? сделать явные методы, называемые close() как для A, так и для B? - person olamundo; 11.08.2009
comment
Более того, wait() работает не лучше, чем delete в eclipse - попробуйте нажать stop, и вы увидите, что exit не вызывается... - person olamundo; 12.08.2009