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"