有没有办法杀死一个线程?

时间:2008-11-27 14:55:54

标签: python multithreading kill terminate

是否可以在不设置/检查任何标志/信号量/等的情况下终止正在运行的线程?

29 个答案:

答案 0 :(得分:602)

在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 )

(基于Tomer Filiba的Killable Threads。有关PyThreadState_SetAsyncExc的返回值的引用似乎来自old version of Python。)

如文档中所述,这不是一个神奇的子弹,因为如果线程在Python解释器之外忙,它就不会捕获中断。

此代码的良好使用模式是让线程捕获特定异常并执行清理。这样,您可以中断任务并仍然进行适当的清理。

答案 1 :(得分:105)

没有官方API可以做到这一点,没有。

您需要使用平台API来终止线程,例如pthread_kill,或TerminateThread。您可以访问此类API,例如通过pythonwin,或通过ctypes。

请注意,这本质上是不安全的。它可能会导致无法收集的垃圾(来自堆栈帧的局部变量变成垃圾),并且如果被杀死的线程在被杀死时具有GIL,则可能导致死锁。

答案 2 :(得分:78)

multiprocessing.Process可以p.terminate()

在我想杀死一个线程但不想使用flags / locks / signals / semaphores / events /的情况下,我将线程提升为完整的进程。对于仅使用几个线程的代码,开销并不是那么糟糕。

E.g。这样可以轻松终止执行阻塞I / O的辅助“线程”

转换非常简单:在相关代码中,将所有threading.Thread替换为multiprocessing.Process,将所有queue.Queue替换为multiprocessing.Queue,并将所需的p.terminate()调用添加到您的父进程想要​​杀死其子p

Python doc

答案 3 :(得分:62)

如果您尝试终止整个程序,可以将该线程设置为“守护程序”。看到 Thread.daemon

答案 4 :(得分:33)

这基于thread2 -- killable threads (Python recipe)

你需要调用PyThreadState_SetasyncExc(),它只能通过ctypes获得。

这仅在Python 2.7.3上进行了测试,但它可能适用于其他最近的2.x版本。

import ctypes

def terminate_thread(thread):
    """Terminates a python thread from another thread.

    :param thread: a threading.Thread instance
    """
    if not thread.isAlive():
        return

    exc = ctypes.py_object(SystemExit)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        ctypes.c_long(thread.ident), exc)
    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(thread.ident, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

答案 5 :(得分:32)

你不应该在没有合作的情况下强行杀死一个线程。

杀死一个线程会删除尝试/最后阻止设置的任何保证,这样你就可以锁定锁,打开文件等等。

你唯一可以争辩说强行杀死线程是一个好主意,就是快速杀死一个程序,但绝不是单线程。

答案 6 :(得分:30)

正如其他人所说,规范是设置停止标志。对于轻量级的东西(没有Thread的子类,没有全局变量),lambda回调是一个选项。 (请注意if stop()中的括号。)

import threading
import time

def do_work(id, stop):
    print("I am thread", id)
    while True:
        print("I am thread {} doing something".format(id))
        if stop():
            print("  Exiting loop.")
            break
    print("Thread {}, signing off".format(id))


def main():
    stop_threads = False
    workers = []
    for id in range(0,3):
        tmp = threading.Thread(target=do_work, args=(id, lambda: stop_threads))
        workers.append(tmp)
        tmp.start()
    time.sleep(3)
    print('main: done sleeping; time to stop the threads.')
    stop_threads = True
    for worker in workers:
        worker.join()
    print('Finis.')

if __name__ == '__main__':
    main()

使用始终刷新(print())的pr()函数替换sys.stdout.flush()可能会提高shell输出的精度。

(仅在Windows / Eclipse / Python3.3上测试)

答案 7 :(得分:22)

在Python中,你根本无法直接杀死一个线程。

如果你真的不需要一个线程(!),你可以做的,而不是使用threading package ,是使用 multiprocessing package 。在这里,要杀死进程,您只需调用方法:

yourProcess.terminate()  # kill the process!

Python将终止你的进程(在Unix上通过SIGTERM信号,而在Windows上通过TerminateProcess()调用)。使用队列或管道时要注意使用它! (它可能会破坏队列/管道中的数据)

请注意,multiprocessing.Eventmultiprocessing.Semaphore的工作方式与threading.Eventthreading.Semaphore完全相同。事实上,第一批是后者的克隆。

如果您真的需要使用Thread,则无法直接杀死它。但是,您可以使用“守护程序线程”。实际上,在Python中,Thread可以标记为守护程序

yourThread.daemon = True  # set the Thread as a "daemon thread"

当没有剩下活着的非守护程序线程时,主程序将退出。换句话说,当您的主线程(当然是非守护程序线程)将完成其操作时,即使仍有一些守护程序线程正在运行,程序也会退出。

请注意,在调用daemon方法之前,必须将线程设置为start()

当然,您可以而且应该daemon使用multiprocessing。这里,当主进程退出时,它会尝试终止所有守护进程的子进程。

最后,请注意,sys.exit()os.kill()不是选择。

答案 8 :(得分:13)

您可以通过在将退出线程的线程中安装trace来终止线程。有关一种可能的实现,请参阅附件链接。

Kill a thread in Python

答案 9 :(得分:9)

最好不要杀死一个帖子。 一种方法可能是在线程的循环中引入一个“try”块,并在你想要停止线程时抛出一个异常(例如一个break / return / ...停止你的for / while / ...)。 我在我的应用程序上使用了它,它可以工作......

答案 10 :(得分:8)

绝对可以实现Thread.stop方法,如以下示例代码所示:

import sys
import threading
import time


class StopThread(StopIteration):
    pass

threading.SystemExit = SystemExit, StopThread


class Thread2(threading.Thread):

    def stop(self):
        self.__stop = True

    def _bootstrap(self):
        if threading._trace_hook is not None:
            raise ValueError('Cannot run thread with tracing!')
        self.__stop = False
        sys.settrace(self.__trace)
        super()._bootstrap()

    def __trace(self, frame, event, arg):
        if self.__stop:
            raise StopThread()
        return self.__trace


class Thread3(threading.Thread):

    def _bootstrap(self, stop_thread=False):
        def stop():
            nonlocal stop_thread
            stop_thread = True
        self.stop = stop

        def tracer(*_):
            if stop_thread:
                raise StopThread()
            return tracer
        sys.settrace(tracer)
        super()._bootstrap()

###############################################################################


def main():
    test1 = Thread2(target=printer)
    test1.start()
    time.sleep(1)
    test1.stop()
    test1.join()
    test2 = Thread2(target=speed_test)
    test2.start()
    time.sleep(1)
    test2.stop()
    test2.join()
    test3 = Thread3(target=speed_test)
    test3.start()
    time.sleep(1)
    test3.stop()
    test3.join()


def printer():
    while True:
        print(time.time() % 1)
        time.sleep(0.1)


def speed_test(count=0):
    try:
        while True:
            count += 1
    except StopThread:
        print('Count =', count)

if __name__ == '__main__':
    main()

Thread3类似乎运行代码的速度比Thread2类快大约33%。

答案 11 :(得分:6)

from ctypes import *
pthread = cdll.LoadLibrary("libpthread-2.15.so")
pthread.pthread_cancel(c_ulong(t.ident))

t 是您的Thread对象。

阅读python源代码(Modules/threadmodule.cPython/thread_pthread.h),您可以看到Thread.identpthread_t类型,因此您可以执行pthread可以执行的任何操作在python中使用libpthread

答案 12 :(得分:6)

以下解决方法可用于杀死线程:

kill_threads = False

def doSomething():
    global kill_threads
    while True:
        if kill_threads:
            thread.exit()
        ......
        ......

thread.start_new_thread(doSomething, ())

这甚至可以用于从主线程终止其代码在另一个模块中编写的线程。我们可以在该模块中声明一个全局变量,并使用它来终止在该模块中生成的线程。

我通常使用它来终止程序出口处的所有线程。这可能不是终止线程的完美方式,但可以提供帮助。

答案 13 :(得分:4)

我想补充的一点是,如果您阅读threading lib Python中的官方文档,建议您避免使用"恶魔"线程,当你不希望线程突然结束时,标志是Paolo Rovelli mentioned

来自官方文件:

  

守护程序线程在关闭时突然停止。他们的资源(例如打开文件,数据库事务等)可能无法正确发布。如果您希望线程正常停止,请使它们成为非守护进程并使用合适的信号机制,例如事件。

我认为创建守护线程取决于你的应用程序,但总的来说(在我看来)最好避免杀死它们或使它们成为守护进程。在多处理中,您可以使用is_alive()来检查流程状态,并且"终止"完成它们(你也避免GIL问题)。但是,当您在Windows中执行代码时,有时会发现更多问题。

永远记住,如果你有"活动线程",Python解释器将运行等待它们。 (因为这个守护神可以帮助你,如果不是突然结束)。

答案 14 :(得分:4)

我已经迟到了这个游戏,但我一直在与a similar question进行摔跤,以下似乎都能完美地解决这个问题并让我做一些基本的线程状态检查和守护进程子线程退出时清理:

import threading
import time
import atexit

def do_work():

  i = 0
  @atexit.register
  def goodbye():
    print ("'CLEANLY' kill sub-thread with value: %s [THREAD: %s]" %
           (i, threading.currentThread().ident))

  while True:
    print i
    i += 1
    time.sleep(1)

t = threading.Thread(target=do_work)
t.daemon = True
t.start()

def after_timeout():
  print "KILL MAIN THREAD: %s" % threading.currentThread().ident
  raise SystemExit

threading.Timer(2, after_timeout).start()

收率:

0
1
KILL MAIN THREAD: 140013208254208
'CLEANLY' kill sub-thread with value: 2 [THREAD: 140013674317568]

答案 15 :(得分:3)

这是另一种方法,但代码非常干净和简单,可在 2021 年在 Python 3.7 中运行:

import ctypes 

def kill_thread(thread):
    """
    thread: a threading.Thread object
    """
    thread_id = thread.ident
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, ctypes.py_object(SystemExit))
    if res > 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
        print('Exception raise failure')

改编自此处:https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/

答案 16 :(得分:3)

如果您明确地将time.sleep()作为线程的一部分进行调用(例如轮询某些外部服务),Phillipe方法的改进就是使用event的{​​{1}}中的超时方法wait()

例如:

sleep()

然后运行它

import threading

class KillableThread(threading.Thread):
    def __init__(self, sleep_interval=1):
        super().__init__()
        self._kill = threading.Event()
        self._interval = sleep_interval

    def run(self):
        while True:
            print("Do Something")

            # If no kill signal is set, sleep for the interval,
            # If kill signal comes in while sleeping, immediately
            #  wake up and handle
            is_killed = self._kill.wait(self._interval)
            if is_killed:
                break

        print("Killing Thread")

    def kill(self):
        self._kill.set()

使用t = KillableThread(sleep_interval=5) t.start() # Every 5 seconds it prints: #: Do Something t.kill() #: Killing Thread 代替wait()并定期检查事件的优点是,您可以在较长的睡眠间隔内编程,线程几乎立即停止(否则将是{{在我看来,处理退出的代码要简单得多。

答案 17 :(得分:1)

有一个为此目的而构建的库stopit。尽管此处列出的某些注意事项仍然适用,但是至少该库提供了一种常规的,可重复的技术来实现所述目标。

答案 18 :(得分:0)

Python 版本:3.8

使用守护线程来执行我们想要的,如果我们想要终止守护线程,我们只需要让父线程退出,然后系统就会终止父线程创建的守护线程。

同时支持协程和协程功能。

def main():
    start_time = time.perf_counter()
    t1 = ExitThread(time.sleep, (10,), debug=False)
    t1.start()
    time.sleep(0.5)
    t1.exit()
    try:
        print(t1.result_future.result())
    except concurrent.futures.CancelledError:
        pass
    end_time = time.perf_counter()
    print(f"time cost {end_time - start_time:0.2f}")

下面是ExitThread源代码

import concurrent.futures
import threading
import typing
import asyncio


class _WorkItem(object):
    """ concurrent\futures\thread.py

    """

    def __init__(self, future, fn, args, kwargs, *, debug=None):
        self._debug = debug
        self.future = future
        self.fn = fn
        self.args = args
        self.kwargs = kwargs

    def run(self):
        if self._debug:
            print("ExitThread._WorkItem run")
        if not self.future.set_running_or_notify_cancel():
            return

        try:
            coroutine = None
            if asyncio.iscoroutinefunction(self.fn):
                coroutine = self.fn(*self.args, **self.kwargs)
            elif asyncio.iscoroutine(self.fn):
                coroutine = self.fn
            if coroutine is None:
                result = self.fn(*self.args, **self.kwargs)
            else:
                result = asyncio.run(coroutine)
            if self._debug:
                print("_WorkItem done")
        except BaseException as exc:
            self.future.set_exception(exc)
            # Break a reference cycle with the exception 'exc'
            self = None
        else:
            self.future.set_result(result)


class ExitThread:
    """ Like a stoppable thread

    Using coroutine for target then exit before running may cause RuntimeWarning.

    """

    def __init__(self, target: typing.Union[typing.Coroutine, typing.Callable] = None
                 , args=(), kwargs={}, *, daemon=None, debug=None):
        #
        self._debug = debug
        self._parent_thread = threading.Thread(target=self._parent_thread_run, name="ExitThread_parent_thread"
                                               , daemon=daemon)
        self._child_daemon_thread = None
        self.result_future = concurrent.futures.Future()
        self._workItem = _WorkItem(self.result_future, target, args, kwargs, debug=debug)
        self._parent_thread_exit_lock = threading.Lock()
        self._parent_thread_exit_lock.acquire()
        self._parent_thread_exit_lock_released = False  # When done it will be True
        self._started = False
        self._exited = False
        self.result_future.add_done_callback(self._release_parent_thread_exit_lock)

    def _parent_thread_run(self):
        self._child_daemon_thread = threading.Thread(target=self._child_daemon_thread_run
                                                     , name="ExitThread_child_daemon_thread"
                                                     , daemon=True)
        self._child_daemon_thread.start()
        # Block manager thread
        self._parent_thread_exit_lock.acquire()
        self._parent_thread_exit_lock.release()
        if self._debug:
            print("ExitThread._parent_thread_run exit")

    def _release_parent_thread_exit_lock(self, _future):
        if self._debug:
            print(f"ExitThread._release_parent_thread_exit_lock {self._parent_thread_exit_lock_released} {_future}")
        if not self._parent_thread_exit_lock_released:
            self._parent_thread_exit_lock_released = True
            self._parent_thread_exit_lock.release()

    def _child_daemon_thread_run(self):
        self._workItem.run()

    def start(self):
        if self._debug:
            print(f"ExitThread.start {self._started}")
        if not self._started:
            self._started = True
            self._parent_thread.start()

    def exit(self):
        if self._debug:
            print(f"ExitThread.exit exited: {self._exited} lock_released: {self._parent_thread_exit_lock_released}")
        if self._parent_thread_exit_lock_released:
            return
        if not self._exited:
            self._exited = True
            if not self.result_future.cancel():
                if self.result_future.running():
                    self.result_future.set_exception(concurrent.futures.CancelledError())

答案 19 :(得分:0)

  

这是一个错误的答案,请参阅评论

以下是如何操作:

from threading import *

...

for thread in enumerate():
    if thread.isAlive():
        try:
            thread._Thread__stop()
        except:
            print(str(thread.getName()) + ' could not be terminated'))

给它几秒钟,然后你的线程应该停止。另请查看thread._Thread__delete()方法。

为方便起见,我建议使用thread.quit()方法。例如,如果您的线程中有套接字,我建议在套接字句柄类中创建quit()方法,终止套接字,然后在thread._Thread__stop()内运行quit()

答案 20 :(得分:0)

如@Kozyarchuk的answer中所述,安装跟踪有效。由于此答案不包含任何代码,因此下面是一个可用的可用示例:

import sys, threading, time 

class TraceThread(threading.Thread): 
    def __init__(self, *args, **keywords): 
        threading.Thread.__init__(self, *args, **keywords) 
        self.killed = False
    def start(self): 
        self._run = self.run 
        self.run = self.settrace_and_run
        threading.Thread.start(self) 
    def settrace_and_run(self): 
        sys.settrace(self.globaltrace) 
        self._run()
    def globaltrace(self, frame, event, arg): 
        return self.localtrace if event == 'call' else None
    def localtrace(self, frame, event, arg): 
        if self.killed and event == 'line': 
            raise SystemExit() 
        return self.localtrace 

def f(): 
    while True: 
        print('1') 
        time.sleep(2)
        print('2') 
        time.sleep(2)
        print('3') 
        time.sleep(2)

t = TraceThread(target=f) 
t.start() 
time.sleep(2.5) 
t.killed = True

它在打印12之后停止。 3未打印。

答案 21 :(得分:0)

仅基于@SCB的想法(正是我所需要的)来创建具有自定义函数的KillableThread子类:

from threading import Thread, Event

class KillableThread(Thread):
    def __init__(self, sleep_interval=1, target=None, name=None, args=(), kwargs={}):
        super().__init__(None, target, name, args, kwargs)
        self._kill = Event()
        self._interval = sleep_interval
        print(self._target)

    def run(self):
        while True:
            # Call custom function with arguments
            self._target(*self._args)

            # If no kill signal is set, sleep for the interval,
            # If kill signal comes in while sleeping, immediately
            #  wake up and handle
            is_killed = self._kill.wait(self._interval)
            if is_killed:
                break

        print("Killing Thread")

    def kill(self):
        self._kill.set()

if __name__ == '__main__':

    def print_msg(msg):
        print(msg)

    t = KillableThread(10, print_msg, args=("hello world"))
    t.start()
    time.sleep(6)
    print("About to kill thread")
    t.kill()

自然,就像@SBC一样,线程不等待运行新循环来停止。在此示例中,您将在“关于杀死线程”之后看到“杀死线程”消息,而不是再等待4秒钟来完成线程(因为我们已经睡了6秒钟)。

KillableThread构造函数中的第二个参数是您的自定义函数(此处为print_msg)。 Args参数是在此处调用函数((“ hello world”))时将使用的参数。

答案 22 :(得分:0)

假设您要具有多个具有相同功能的线程,这是恕我直言,最简单的实现是通过id停止一个线程:

import time
from threading import Thread

def doit(id=0):
    doit.stop=0
    print("start id:%d"%id)
    while 1:
        time.sleep(1)
        print(".")
        if doit.stop==id:
            doit.stop=0
            break
    print("end thread %d"%id)

t5=Thread(target=doit, args=(5,))
t6=Thread(target=doit, args=(6,))

t5.start() ; t6.start()
time.sleep(2)
doit.stop =5  #kill t5
time.sleep(2)
doit.stop =6  #kill t6

不错的是,您可以拥有多个相同和不同的功能,并通过functionname.stop停止所有功能

如果您只希望函数的一个线程,则无需记住ID。如果doit.stop> 0,就停下来。

答案 23 :(得分:0)

ØMQ - 项目的创始人之一Pieter Hintjens说,使用ØMQ并避免锁,互斥,事件等同步原语,是编写多线程的最安全和最安全的方法程序:

http://zguide.zeromq.org/py:all#Multithreading-with-ZeroMQ

这包括告诉子线程,它应该取消它的工作。这可以通过为线程配备一个ØMQ套接字并在该套接字上轮询一条消息说它应该取消来完成。

该链接还提供了一个关于使用ØMQ的多线程python代码的示例。

答案 24 :(得分:0)

虽然它相当陈旧,this可能是一些方便的解决方案:

  

扩展线程模块功能的小模块 -   允许一个线程在另一个线程的上下文中引发异常   线。通过提升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)

因此,它允许“线程在另一个线程的上下文中引发异常”,这样终止的线程就可以处理终止而无需定期检查中止标志。

但是,根据其original source,此代码存在一些问题。

  
      
  • 只有在执行python字节码时才会引发异常。如果您的线程调用本机/内置阻塞函数,则   只有在执行返回python时才会引发异常   码。      
        
    • 如果内置函数在内部调用PyErr_Clear(),则会出现问题,这会有效地取消挂起的异常。   你可以尝试再次提高它。
    •   
  •   
  • 只能安全地引发异常类型。异常实例可能会导致意外行为,因此受到限制。      
  •   
  • 我要求在内置线程模块中公开这个函数,但是因为ctypes已成为标准库(从2.5开始),而这个
      功能不太可能与实现无关,可能会保留   未曝光。
  •   

答案 25 :(得分:0)

使用setDaemon(True)启动子线程。

def bootstrap(_filename):
    mb = ModelBootstrap(filename=_filename) # Has many Daemon threads. All get stopped automatically when main thread is stopped.

t = threading.Thread(target=bootstrap,args=('models.conf',))
t.setDaemon(False)

while True:
    t.start()
    time.sleep(10) # I am just allowing the sub-thread to run for 10 sec. You can listen on an event to stop execution.
    print('Thread stopped')
    break

答案 26 :(得分:0)

这似乎适用于Windows 7上的pywin32

my_thread = threading.Thread()
my_thread.start()
my_thread._Thread__stop()

答案 27 :(得分:-1)

您可以在进程中执行命令,然后使用进程ID终止它。 我需要在两个线程之间进行同步,其中一个线程本身不会返回。

processIds = []

def executeRecord(command):
    print(command)

    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    processIds.append(process.pid)
    print(processIds[0])

    #Command that doesn't return by itself
    process.stdout.read().decode("utf-8")
    return;


def recordThread(command, timeOut):

    thread = Thread(target=executeRecord, args=(command,))
    thread.start()
    thread.join(timeOut)

    os.kill(processIds.pop(), signal.SIGINT)

    return;

答案 28 :(得分:-2)

如果您确实需要杀死子任务的能力,请使用备用实现。 multiprocessinggevent都支持不分青红皂白地杀死“线程”。

Python的线程不支持取消。想都别想。您的代码很可能会死锁,损坏或泄漏内存,或者有其他无意识的“有趣”难以调试的影响,这种影响很少发生且不确定。