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


当前回答

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

其他回答

我对这个游戏已经很晚了,但我一直在与一个类似的问题作斗争,下面的内容似乎为我完美地解决了这个问题,并且让我在守护子线程退出时做一些基本的线程状态检查和清理:

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]

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

在Python中杀死一个线程

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

t是线程对象。

阅读python源代码(Modules/threadmodule.c和python /thread_pthread.h),你可以看到Thread。Ident是一个pthread_t类型,所以你可以使用libpthread在python中做任何pthread可以做的事情。

我想补充的一件事是,如果你阅读threading lib Python的官方文档,建议避免使用“恶魔”线程,当你不希望线程突然结束时,带有Paolo Rovelli提到的标志。

来自官方文件:

守护进程线程在关机时突然停止。它们的资源(如打开的文件、数据库事务等)可能无法正确释放。如果您希望线程优雅地停止,请将它们设置为非守护进程,并使用适当的信号机制(如Event)。

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

并且永远记住,如果你有“活动线程”,Python解释器将运行等待它们。(因为这个守护程序可以帮助你如果不重要的事情突然结束)。

这是一个糟糕的答案,请看评论

以下是如何做到这一点:

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()方法,终止套接字,然后在你的quit()中运行一个thread. _thread__stop()。