Threading: Method trigger after thred finished

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Oct 19 23:55:44 EDT 2011


On Wed, 19 Oct 2011 13:14:21 -0700, markus.mj wrote:

> Hi,
> 
> I am looking for help with following problem. I scripted threaded
> database query, with session open per thread, and queries delivered
> through queue. Every open DB session must be closed with "abort" or
> "commit", however on which event should I trigger the DB disconnect?
> Ideally it would close the DB as the thread class gets deconstructed,
> but "__del__" does never fire.

The __del__ destructor method is not guaranteed to be called in a timely 
fashion, if at all. My *guess* is that the main Python environment is 
shutting down when the daemon threads get killed, and the __del__ method 
never gets a chance to run.

To be honest, I'm not sure why you are using daemon threads. It seems to 
me that blocking until the queue is empty makes the use of daemon threads 
pointless, but I'm not experienced enough with threads to be sure.

The usual advice is to explicitly call destructors rather than rely on 
automatic __del__ methods. Given that, this works for me:


import threading
import Queue
import time

# Fill the queue.
queue = Queue.Queue()
queries = ["query"+str(i) for i in range(10)]
for query in queries:
    queue.put(query)

# Make consumer threads.
class ThreadSql(threading.Thread):
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue
        # Open database connection instance
        self.session = "+++connection+++"  # DbConnect()
        self._open = True

    def run(self):
        while self._open:
            # Grab a query from queue.
            query = self.queue.get()
            # And process it.
            print self, query
            time.sleep(1)
            # Mark the queue job as done.
            self.queue.task_done()

    def close(self):
        print "Closing", self
        # self.session.Disconnect(<abort, commit>)
        self._open = False

threads = [ThreadSql(queue) for _ in range(4)]
for t in threads:
    t.setDaemon(True)
    t.start()

# Wait until the queue is empty, then close the threads.
queue.join()
for t in threads:
    t.close()




-- 
Steven



More information about the Python-list mailing list