Хотя он довольно старый, этот может быть удобным решением для некоторых:
Небольшой модуль, расширяющий функциональность модуля потоковой передачи - позволяет одному потоку поднимать исключений в контексте другого потока. Поднимая
blockquote>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)
Таким образом, он позволяет «потоку создавать исключения в контексте другого потока», и таким образом, завершенный поток может обрабатывать прерывание без регулярной проверки флага прерывания.
Однако, согласно его исходному источнику , есть некоторые проблемы с этим кодом.
blockquote>
- Исключение будет возникать только при выполнении байт-кода python. Если ваш поток вызывает встроенную / встроенную функцию блокировки, исключение будет возбуждено только тогда, когда выполнение возвращается к коду python. Также существует проблема, если встроенная функция внутренне вызывает PyErr_Clear (), которая эффективно отменит ваше ожидающее исключение. Вы можете попытаться снова поднять его.
- Только безопасные типы исключений могут быть подняты. Экземпляры исключений, вероятно, вызовут неожиданное поведение и, таким образом, будут ограничены. Например: t1.raise_exc (TypeError), а не t1.raise_exc (TypeError ("blah")). ИМХО, это ошибка, и я сообщил об этом как об одном. Для получения дополнительной информации http://mail.python.org/pipermail/python-dev/2006-August/068158.html
- Я попросил разоблачить эту функцию в встроенном -in, но поскольку ctypes стал стандартной библиотекой (по версии 2.5), и эта функция вряд ли будет реализована-агностична, ее можно сохранить неэкспонированной.