Threading: Method trigger after thred finished

Markus markus.mj at gmail.com
Thu Oct 20 03:05:27 EDT 2011


On Oct 20, 5:55 am, Steven D'Aprano <steve
+comp.lang.pyt... at pearwood.info> wrote:
> 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

Hi Steven,

great point with the explicit call of destructor.
I did a quick test and it is behaving exactly like I need.

Thank you very much!
Markus



More information about the Python-list mailing list