Это обычно - плохой шаблон для уничтожения потока резко в Python и на любом языке. Думайте о следующих случаях:
хороший способ обработать это, если можно предоставить его (при управлении собственными потоками) состоит в том, чтобы иметь флаг exit_request, который каждый распараллеливает, проверяет равный интервал, чтобы видеть, пора ли ему выйти.
, Например:
import threading
class StoppableThread(threading.Thread):
"""Thread class with a stop() method. The thread itself has to check
regularly for the stopped() condition."""
def __init__(self):
super(StoppableThread, self).__init__()
self._stop_event = threading.Event()
def stop(self):
self._stop_event.set()
def stopped(self):
return self._stop_event.is_set()
В этом коде, необходимо звонить stop()
на потоке, когда Вы хотите, чтобы он вышел, и ожидал потока для выхода из правильно использования join()
. Поток должен проверить флаг остановки равномерно.
существуют случаи однако, когда действительно необходимо уничтожить поток. Пример - при обертывании внешней библиотеки, которая занята для длинных вызовов, и Вы хотите прервать его.
следующий код позволяет (с некоторыми ограничениями) повышать Исключение в потоке Python:
def _async_raise(tid, exctype):
'''Raises an exception in the threads with id tid'''
if not inspect.isclass(exctype):
raise TypeError("Only types can be raised (not instances)")
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid),
ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid 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(ctypes.c_long(tid), None)
raise SystemError("PyThreadState_SetAsyncExc failed")
class ThreadWithExc(threading.Thread):
'''A thread class that supports raising exception in the thread from
another thread.
'''
def _get_my_tid(self):
"""determines this (self's) thread id
CAREFUL : this function is executed in the context of the caller
thread, to get the identity of the thread represented by this
instance.
"""
if not self.isAlive():
raise threading.ThreadError("the thread is not active")
# do we have it cached?
if hasattr(self, "_thread_id"):
return self._thread_id
# no, look for it in the _active dict
for tid, tobj in threading._active.items():
if tobj is self:
self._thread_id = tid
return tid
# TODO: in python 2.6, there's a simpler way to do : self.ident
raise AssertionError("could not determine the thread's id")
def raiseExc(self, exctype):
"""Raises the given exception type in the context of this thread.
If the thread is busy in a system call (time.sleep(),
socket.accept(), ...), the exception is simply ignored.
If you are sure that your exception should terminate the thread,
one way to ensure that it works is:
t = ThreadWithExc( ... )
...
t.raiseExc( SomeException )
while t.isAlive():
time.sleep( 0.1 )
t.raiseExc( SomeException )
If the exception is to be caught by the thread, you need a way to
check that your thread has caught it.
CAREFUL : this function is executed in the context of the
caller thread, to raise an excpetion in the context of the
thread represented by this instance.
"""
_async_raise( self._get_my_tid(), exctype )
(На основе Потоки Killable Tomer Filiba. Кавычка о возвращаемом значении PyThreadState_SetAsyncExc
, кажется, от старая версия Python .)
, Как отмечено в документации, это не чудодейственное средство, потому что, если поток занят вне интерпретатора Python, это не поймает прерывание.
А хороший шаблон использования этого кода должен иметь поток, ловят определенное исключение и выполняют очистку. Тем путем можно прервать задачу и все еще иметь надлежащую очистку.
Если Вы хотите сохранить свою технологию Optimus Nvidia для сохранения ресурса аккумулятора, Вы могли бы использовать Шмеля от способного - добираются, как заявил Danatela. Затем optirun name-of-the-program
позволит Вам устанавливать name-of-the-program программу для выполнения с GPU Nvidia.
, Если Вы не заботитесь о ресурсе аккумулятора, все, которое необходимо сделать, должен переключить от Optimus Nvidia до Вас Nvidia GEFORCE в BIOS.