I'd say inject that code in the beginning of each Thread's run().
If you don't want to change that code, you could do monkeypatch it e.g. like this:
Worker.run = lambda *a: [init_pdb(), Worker.run(*a)][-1]
Or like this:
def wrapper(*a):
# init pdb here
Worker.run(*a)
Worker.run = wrapper
If you wanna go real hardcore, you can override threading.Thread.start, or possibly threading.Thread altogether before you import other modules, e.g.:
class DebuggedThread(threading.Thread):
def __init__(self):
super(DebuggedThread, self).__init__()
self._real_run = self.run
self.run = self._debug_run
def _debug_run(self):
# initialize debugger here
self._real_run()
threading.Thread = DebuggedThread