Skip to content Skip to sidebar Skip to footer

Python Thread Not Exiting With Atexit

Here is my script. When I run it in a shell it just hangs indefinitely whereas I would expect it to terminate cleanly. import logging from logging import StreamHandler import pymst

Solution 1:

I got something working, have a look:

import queue
import threading


classWorker:
    def__init__(self):
        self.queue = queue.Queue()
        threading.Thread(target=self._worker).start()

    def_worker(self):
        print("starting thread")
        whileTrue:
            record = self.queue.get()
            if record isNone:
                print("exiting")
                breakprint(f"Got message: {record}")

    defemit(self, record):
        self.queue.put(record)


classWrapper:
    def__init__(self):
        self._worker = Worker()

    def__del__(self):
        print("Wrapper is being deleted")
        self._worker.emit(None)

    defemit(self, record):
        self._worker.emit(record)

defmain():
    worker = Wrapper()
    worker.emit("foo")
    worker.emit("bar")
    print("main exits")


if __name__ == "__main__":
    main()

The point here is that when main exits, worker (which is an instance of Wrapper) goes out of scope, and its __del__ method is called, and it sends stop message to a real worker object.

The results of running this code ("Got message" lines can be in different places, of course):

startingthreadmainexitsWrapperisbeingdeletedGot message:fooGot message:barexiting

Solution 2:

As pointed out by avysk, the problem is likely that atexit handlers fire too late, after the waiting for the non-daemon threads is already (supposed to be) done, which leads to deadlock.

If I were you, I'd just add a call like TeamsHandler.finish() at the end of if __name__ == '__main__' block, and modify TeamsHandler along these lines (untested):

_queues = []

classTeamsHandler(StreamHandler):
    def__init__(self, channel_url):
        super().__init__()
        self.channel_url = channel_url
        self.queue = queue.Queue()
        self.thread = threading.Thread(target=self._worker)
        self.thread.start()
        _queues.append(self.queue)

    def_worker(self):
        whileTrue:
            record = self.queue.get()
            if record isNone:
                break
            msg = self.format(record)
            print(msg)

    defemit(self, record):
        # enqueue the record to log and return control to the caller
        self.queue.put(record)

    @staticmethoddeffinish(self):
        for q in _queues:
            q.put(None)
        del _queues[:]

Post a Comment for "Python Thread Not Exiting With Atexit"