How to pass and run a callback method in Python How to pass and run a callback method in Python python python

How to pass and run a callback method in Python


The thread can't call the manager unless it has a reference to the manager. The easiest way for that to happen is for the manager to give it to the thread at instantiation.

class Manager(object):    def new_thread(self):        return MyThread(parent=self)    def on_thread_finished(self, thread, data):        print thread, dataclass MyThread(Thread):    def __init__(self, parent=None):        self.parent = parent        super(MyThread, self).__init__()    def run(self):        # ...        self.parent and self.parent.on_thread_finished(self, 42)mgr    = Manager()thread = mgr.new_thread()thread.start()

If you want to be able to assign an arbitrary function or method as a callback, rather than storing a reference to the manager object, this becomes a bit problematic because of method wrappers and such. It's hard to design the callback so it gets a reference to both the manager and the thread, which is what you will want. I worked on that for a while and did not come up with anything I'd consider useful or elegant.


Anything wrong with doing it this way?

from threading import Threadclass Manager():    def Test(self):        MyThread(self.on_thread_finished).start()    def on_thread_finished(self, data):        print "on_thread_finished:", dataclass MyThread(Thread):    def __init__(self, callback):        Thread.__init__(self)        self.callback = callback    def run(self):        data = "hello"        self.callback(data)m = Manager()m.Test() # prints "on_thread_finished: hello"


If you want the main thread to wait for children threads to finish execution, you are probably better off using some kind of synchronization mechanism. If simply being notified when one or more threads has finished executing, a Condition is enough:

import threadingclass MyThread(threading.Thread):    def __init__(self, condition):        threading.Thread.__init__(self)        self.condition = condition    def run(self):        print "%s done" % threading.current_thread()        with self.condition:            self.condition.notify()condition = threading.Condition()condition.acquire()thread = MyThread(condition)thread.start()condition.wait()

However, using a Queue is probably better, as it makes handling multiple worker threads a bit easier.