是否有可能终止一个正在运行的线程而不设置/检查任何标志/信号/等等?


当前回答

你不应该在没有与线程合作的情况下强行终止线程。

杀死一个线程消除了try/finally阻塞设置的任何保证,所以你可能会让锁锁定,文件打开等等。

唯一可以认为强制终止线程是一个好主意的情况是快速终止程序,但绝不是单个线程。

其他回答

你不应该在没有与线程合作的情况下强行终止线程。

杀死一个线程消除了try/finally阻塞设置的任何保证,所以你可能会让锁锁定,文件打开等等。

唯一可以认为强制终止线程是一个好主意的情况是快速终止程序,但绝不是单个线程。

这是基于thread2—可杀死线程ActiveState配方。

您需要调用PyThreadState_SetAsyncExc(),它只能通过ctypes模块使用。

这只在Python 2.7.3上进行了测试,但它很可能与最近的其他2一起工作。x版本。PyThreadState_SetAsyncExc()仍然存在于Python 3中以实现向后兼容性(但我还没有测试它)。

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

您可以在进程中执行命令,然后使用进程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;

另一种方法是使用signal.pthread_kill发送一个停止信号。

from signal import pthread_kill, SIGTSTP
from threading import Thread
from itertools import count
from time import sleep

def target():
    for num in count():
        print(num)
        sleep(1)

thread = Thread(target=target)
thread.start()
sleep(5)
pthread_kill(thread.ident, SIGTSTP)

结果

0
1
2
3
4

[14]+  Stopped

正如其他人所提到的,规范是设置一个停止标志。对于一些轻量级的东西(没有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上测试)