首页 > 解决方案 > 线程运行时未调用 atexit

问题描述

我希望依靠 atexit 来停止一个否则会阻塞的线程。

我发现当我在线程运行时调用 sys.exit() 时注册的方法不会被调用。

我发现如果线程没有运行,就会调用该函数。

    import os
    import atexit
    import threading
    import sys


    class Watcher:
        def __init__(self, to_watch, callback):
            self.path_to_watch = to_watch
            self.stop_flag = False
            self._monitor_thread = threading.Thread(target=self.monitor_thread)
            self._monitor_thread.start()

            atexit.register(self.stop)

        def stop(self):
            print(f'stopping watcher on {self.path_to_watch}')
            self.stop_flag=True


        def monitor_thread(self):
            while not self.stop_flag:
                pass

    if __name__ == '__main__':
        def my_callback( file, action):
            print(file, action)

        dw = Watcher('.', my_callback)
        sys.exit(0)

这是预期的行为吗?我在 atexit 中没有看到任何关于此的文档。

有没有更好的方法来捕捉主线程正在终止并停止我的线程?

标签: pythonmultithreadingatexit

解决方案


如果您可以构造代码以便(理想情况下)主线程只有一种退出方式,那么 threading.Event 是主线程向一个或多个其他线程发出信号表明该退出的好方法。例子:

import threading
import time
import sys

class Watcher:
    def __init__(self, done):
        self.done = done
        self._monitor_thread = threading.Thread(target=self.monitor_thread)
        self._monitor_thread.start()

    def monitor_thread(self):
        sys.stderr.write("Watcher started\n")
        while not self.done.is_set():
            pass
        sys.stderr.write("Watcher thread exiting\n")

if __name__ == '__main__':
    done = threading.Event()
    Watcher(done)
    time.sleep(5)
    done.set()
    sys.stderr.write("Main thread exiting\n")

推荐阅读