Python:检测父线程是否名为exit()

时间:2019-01-28 00:24:29

标签: python multithreading

我有一个正在后台运行的线程,可以从主线程进行更新:

import threading
from Queue import Queue
from time import sleep

class Animation(threading.Thread):

    SIGNAL_STOP = 'stop'

    def __init__(self, framerate):
        threading.Thread.__init__(self)
        self.queue = Queue()
        self.framerate = framerate

    def tell(self, data):
        self.queue.put(data)

    def stop(self):
        self.tell(Animation.SIGNAL_STOP)

    def loop(self):
        # Override this method to implement animation loop
        pass

    def update(self, data):
        # Override this method to implement the state update
        pass

    def cleanup(self):
       # Override this method to implement what's done when the animation is stopped
       pass

    def run(self):
        while True:
            if not self.queue.empty():
                data = self.queue.get()
                if data == Animation.SIGNAL_STOP:
                    break;
                self.update(data)
            self.loop()
            sleep(1. / self.framerate)

        self.cleanup()


class TestAnimation(Animation):
    def __init__(self, framerate):
        super(TestAnimation, self).__init__(framerate)
        self.num = 0

    def loop(self):
        print 'num =', self.num
        self.num = self.num + 1

    def update(self, data):
        print 'update:', data

    def cleanup(self):
        print 'graceful exit'

print 'start'
ta = TestAnimation(1)
ta.start()
sleep(3)
ta.update(123)
sleep(3)
#ta.stop() # I'd like the animation thread to feel that the parent wants to exit and carry out stopping itself
print 'end'
exit()

我想实现某种方法来检测父线程何时要退出,然后所有正在运行的线程将正常终止。我宁愿代替显式调用运行线程的stop()方法。

1 个答案:

答案 0 :(得分:1)

我相信您可以将其设置为daemon线程,因此当主线程退出时,所有守护线程都随之退出。

因此,您可以在构造函数中将其默认设置为daemon = True,也可以将其设置为start之前

ta = TestAnimation(1)
ta.daemon = True
ta.start()

编辑。由于需要清理线程。

您可以使用thread.Eventatexit的组合来发信号通知守护程序线程,以在退出之前进行清理。

这是一个简单的示例:

import time
import threading
import atexit

signal_to_threads = threading.Event()  # Global signal for threads to stop.

registered_threads = [] # Register all threads into here. 

@atexit.register
def signal_threads():
    print('signaling threads to stop')
    signal_to_threads.set()
    for thread in registered_threads:
        thread.signal.wait()


class TestExit(threading.Thread):
    def __init__(self, *args, **kw):
        registered_threads.append(self)
        self.signal = threading.Event()
        super(TestExit, self).__init__(*args, **kw)
        self.daemon = True  # Ensure is a daemon thread.

    def run(self):
        while True:
            time.sleep(3)
            print('Hi from child thread')
            if signal_to_threads.is_set():
                print('stopping child thread and doing cleanup.')
                # self.do_cleanup()
                self.signal.set()
                break


t = TestExit()
t.start()
print('sleeping for 10 secs.')
time.sleep(10)
print('exiting main thread')

演示:

python test_thread.py
sleeping for 10 secs.
Hi from child thread
Hi from child thread
Hi from child thread
exiting main thread
signaling threads to stop
Hi from child thread
stopping child thread and doing clean up.

由于atexit应该在退出时运行已注册的函数,因此无需紧跟每个退出点来清理线程。