Обновление службы Ссылка Выпуск

Хотя он довольно старый, этот может быть удобным решением для некоторых:

Небольшой модуль, расширяющий функциональность модуля потоковой передачи - позволяет одному потоку поднимать исключений в контексте другого потока. Поднимая SystemExit, вы можете, наконец, уничтожить потоки python.

blockquote>
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. Если ваш поток вызывает встроенную / встроенную функцию блокировки, исключение будет возбуждено только тогда, когда выполнение возвращается к коду 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), и эта функция вряд ли будет реализована-агностична, ее можно сохранить неэкспонированной.
blockquote>

0
задан user1492885 31 December 2018 в 09:33
поделиться