使用__del__停止Python线程

6 投票
2 回答
7474 浏览
提问于 2025-04-16 22:48

我有一个用Python写的多线程程序,运行得很好,但有一个问题,就是当线程在运行时,__del__这个方法没有被调用:

class tt(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.stop_event = threading.Event()

    def __del__(self):
        print "Deleting"
        self.stop_event.set()
        time.sleep(5)

    def run(self):
        self.stop_event.clear()
        while not self.stop_event.isSet():
             self.do_stuff()
        threading.Thread.__init__(self)

    def stop(self):
        self.stop_event.set()

比如说,如果我这样做:

tc = aa()
del tc 

那就没问题(我能看到删除消息、暂停等等)。但是如果我这样做:

tc = aa()
tc.start()
del tc

那么__del__就不会被执行(注意,当我执行tc.start(); tc.stop(); del tc的时候,__del__是会被执行的)。

我是在ipython环境下运行这个程序的。

2 个回答

3

请查看文档

del x 并不是直接调用 x.__del__() — 其实它只是把 x 的引用计数减了一。只有当 x 的引用计数降到零的时候,x.__del__() 才会被调用。

在你的情况中,线程还在运行,并且还有一些(内部的)引用指向它。所以它的引用计数大于一,当你从模块命名空间中删除它时,引用计数仍然大于零。因为它没有被垃圾回收,所以 __del__ 并不会被调用。

8

__del__() 方法是在一个对象被垃圾回收时执行的,而不是当你用 del 删除一个指向这个对象的名字时。后者只是删除了这个名字,可能会导致这个名字指向的对象被垃圾回收,但并不是直接触发的。

一个 threading.Thread 的实例在线程还在运行的时候是不会被垃圾回收的,因为这个实例还在被使用。如果你删除了一个指向这个实例的名字,也不会停止这个线程。

撰写回答