python—有没有办法杀死线程?

cngwdvgl  于 2021-08-25  发布在  Java
关注(0)|答案(20)|浏览(566)

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

mw3dktmi

mw3dktmi16#

这是基于thread2——可终止线程(python配方)
您需要调用pythreadstate_setasyncexc(),该函数仅可通过ctypes使用。
这只在Python2.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")
ozxc1zmp

ozxc1zmp17#

正如其他人所提到的,标准是设置停止标志。对于一些轻量级的东西(没有线程的子类,没有全局变量),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() )可以提高外壳输出的精度。
(仅在windows/eclipse/python3.3上测试)

bis0qfac

bis0qfac18#

如果您试图终止整个程序,可以将线程设置为“守护进程”。请参阅thread.daemon

gcuhipw9

gcuhipw919#

A. multiprocessing.Process 可以 p.terminate() 如果我想杀死一个线程,但不想使用标志/锁/信号/信号量/事件/任何东西,我会将线程升级为完整的进程。对于只使用几个线程的代码,开销并没有那么大。
e、 这样可以方便地终止执行阻塞i/o的助手“线程”
转换很简单:在相关代码中替换所有 threading.Thread 具有 multiprocessing.Process 诸如此类 queue.Queue 具有 multiprocessing.Queue 并添加所需的 p.terminate() 要杀死其子进程的父进程 p 有关详细信息,请参阅python文档 multiprocessing .
例子:

import multiprocessing
proc = multiprocessing.Process(target=your_proc_function, args=())
proc.start()

# Terminate the process

proc.terminate()  # sends a SIGTERM
r6vfmomb

r6vfmomb20#

没有官方的api可以做到这一点。
您需要使用平台api终止线程,例如pthread_kill或terminatethread。您可以通过pythonwin或ctypes访问此类api。
请注意,这本身就是不安全的。它可能会导致无法收集的垃圾(来自成为垃圾的堆栈帧的局部变量),并可能导致死锁,如果被终止的线程在终止时具有gil。

相关问题