Reputation: 31521
Consider this test application for passing arguments to Python threads:
#!/usr/bin/python3
from pprint import pprint
import signal
import sys
import threading
class CallThreads(threading.Thread):
def __init__(self, target, *args):
self._target = target
threading.Thread.__init__(self)
target(*args)
def main(argv):
phrases = ['hello', 'goodbye']
num = 0
for phrase in phrases:
num += 1
thread_handler = CallThreads(someFunction, phrase, num)
thread_handler.daemon = True
thread_handler.start()
return True
def someFunction(a, b):
print("Hi: "+str(a)+" and "+str(b))
return True
def signal_handler(signal, frame):
print(["Got SIGINT!"])
sys.exit(0)
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
main(sys.argv)
In it's current state, it seems as though the for phrase in phrases
loop is waiting for the thread to finish before starting another thread. That is, if someFunction()
takes a long time to complete, then the then next thread will not start until the previous thread returns. Why is this, and how can I work around it while still sending arguments to the threads?
Edit:
I've tried saving the args
array in self._args
in the constructor, and then calling self._target(*self._args)
or self._target(self._args)
in def run (self):
. This actually works in Python 2, but not in Python 3. What should I do?
Edit:
It seems that the problem is that in Python 3, the run
method cannot access the private variables. That is, for the following improved code:
def __init__(self, target, *args):
self._args = args
threading.Thread.__init__(self)
def run(self):
someFunction(*self._args)
Note the following output:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.3/threading.py", line 639, in _bootstrap_inner
self.run()
File "./test.py", line 19, in run
someFunction(*self._args)
TypeError: someFunction() missing 2 required positional arguments: 'a' and 'b'
And adding a pprint(self._args)
to the run()
method indeed shows that the tuple returned is empty. However, changing the variables to non-private works! The following code runs fine:
def __init__(self, target, *args):
self.target = target
self.args = args
threading.Thread.__init__(self)
def run(self):
self.target(*self.args)
Therefore, I can use the application with public variables in Python 3. However, is there any way to use private variables in the CallThreads
class, as in Python 2?
Thanks!
Upvotes: 1
Views: 940
Reputation: 6661
The problem is that you call target(args)
on the constructor of CallThreads
.
Therefore the following call blocks until CallThreads.__init__()
is finished:
thread_handler = CallThreads(someFunction, phrase, num)
Update: One possibility could be the following:
class CallThreads(threading.Thread):
def __init__(self, *args):
self._args = args
threading.Thread.__init__(self)
def run(self):
someFunction(*self._args)
Upvotes: 4