Корневая разница здесь на самом деле не связана ни с сигналами, ни с atexit, а скорее с изменением поведения sys.exit
.
До примерно 2.6.5, sys.exit
(точнее, перехват SystemExitна верхнем уровне) вызовет выход интерпретатора;если бы потоки все еще работали, они были бы прерваны, как с потоками POSIX.
Вокруг 2.6.5, поведение изменилось: эффект sys.exit
теперь по сути такой же, как и возвращение из основной функции.программы.Когда вы делаете , что - в обеих версиях - интерпретатор ожидает соединения всех потоков перед выходом.
Соответствующее изменение заключается в том, что Py_Finalize
теперь вызывает wait_for_thread_shutdown()
возлеtop, там, где это раньше не было.
Это изменение поведения кажется неправильным, в первую очередь потому, что оно больше не работает так, как задокументировано, а именно: «Выход из Python».Практический эффект - больше не выход из Python, а просто выход из потока.(Как примечание: sys.exit
никогда не выходил из Python при вызове из другого потока, но это неясное расхождение с документированным поведением не оправдывает намного большее.)
Я вижу привлекательность новогоповедение: вместо двух способов выхода из основного потока («выход и ожидание потоков» и «немедленный выход»), есть только один, так как sys.exit по сути идентичен простому возврату из верхней функции.Однако это серьезное изменение, которое отличается от задокументированного поведения, которое намного перевешивает это.
Из-за этого изменения после sys.exit
из обработчика сигнала, приведенного выше, интерпретатор бездействует, ожидая выхода потоков, и затем запускаетсяatexit
обработчики после того, как они это делают.Поскольку сам обработчик сообщает потокам о выходе, результатом является тупик.