Хотя он довольно старый, , для некоторых может оказаться удобным решением:
Маленький модуль, который расширяет функциональность модуля потоков -
позволяет одному потоку вызывать исключения в контексте другого
нить. Подняв SystemExit
, вы можете наконец убить потоки Python.
import threading
import ctypes
def _async_raise(tid, excobj):
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(excobj))
if res == 0:
raise ValueError("nonexistent thread id")
elif res > 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
raise SystemError("PyThreadState_SetAsyncExc failed")
class Thread(threading.Thread):
def raise_exc(self, excobj):
assert self.isAlive(), "thread must be started"
for tid, tobj in threading._active.items():
if tobj is self:
_async_raise(tid, excobj)
return
# the thread was alive when we entered the loop, but was not found
# in the dict, hence it must have been already terminated. should we raise
# an exception here? silently ignore?
def terminate(self):
# must raise the SystemExit type, instead of a SystemExit() instance
# due to a bug in PyThreadState_SetAsyncExc
self.raise_exc(SystemExit)
Таким образом, он позволяет «потоку вызывать исключения в контексте другого потока», и, таким образом, завершенный поток может обрабатывать завершение без регулярной проверки флага прерывания.
Однако, согласно исходному источнику , с этим кодом есть некоторые проблемы.
- Исключение будет вызываться только при выполнении байт-кода Python. Если ваш поток вызывает встроенную / встроенную функцию блокировки,
исключение будет возбуждено только тогда, когда выполнение вернется к питону
код.
- Существует также проблема, если встроенная функция внутренне вызывает PyErr_Clear (), что фактически отменяет ожидающее исключение.
Вы можете попытаться поднять его снова.
- Только типы исключений могут быть вызваны безопасно. Экземпляры исключений могут вызывать неожиданное поведение и поэтому ограничены.
- Я попросил выставить эту функцию во встроенном модуле потока, но поскольку ctypes стала стандартной библиотекой (начиная с 2.5), и это
функция, скорее всего, не зависит от реализации, ее можно сохранить
неразоблаченный.