Below is an example code I got from https://tutorialedge.net/python/concurrency/python-threadpoolexecutor-tutorial/
from concurrent.futures import ThreadPoolExecutor
import threading
import random
taskarr = []
def task(n,c):
print("Executing our Task = {} and {}".format(n,c))
print("Task Executed {}".format(threading.current_thread()))
def main():
executor = ThreadPoolExecutor(max_workers=3)
task1 = executor.submit(task(1,'A'))
task2 = executor.submit(task(2,'B'))
if __name__ == '__main__':
main()
in this, if executor.submit is returned to simple variable task1, it works. But my requirement is to return it to an array. so when i do, taskarr[0] = executor.submit(task(1,'A')) it throws error as,
TypeError: 'function' object does not support item assignment
I could not reproduce your TypeError
; apparently you have some more code that you did not show us. As rocksportrocker pointed out in their comment, you can't assign values to an index that does not yet exist, as in your attempt to assign the future returned from executor.submit()
to index 0 of the empty list typearr
. This will raise the mentioned IndexError
.
However, I could produce some TypeError
and that is due to the fact that you call submit
incorrectly.
The Executor documentation defines the parameter fn
to be a callable object, e.g. a function. Now, when you call submit
like you do:
executor.submit(task(1,'A'))
task(1,'A')
is executed in your main thread and its return value (None
in your case) is then passed to the pool thread. The pool thread then tries to execute None(1, 'A')
and raises a TypeError: 'NoneType' object is not callable
, which you don't see, because it is wrapped in the future. You would see it if you called task1.result()
.
That means, that it is your main thread that executes your task instead of your pool threads, as should have become visible from your second print statement in task
:
Task Executed <_MainThread(MainThread, started 11064)>
In order to have your pool threads do the work, you need to pass the function object task
to executor.submit
, like so:
taskarr = []
def task(n,c):
print("Executing our Task = {} and {}".format(n,c))
time.sleep(3) # added this to make sure that two different threads from the pool get a task
print("Task Executed {}".format(threading.current_thread()))
def main():
executor = ThreadPoolExecutor(max_workers=3)
taskarr.append(executor.submit(task, 1,'A'))
taskarr.append(executor.submit(task, 2,'B'))
# to show that the main thread continues to execute
# while the pool threads work on the tasks
print("{}: tasks submitted".format(threading.current_thread().name))
if __name__ == '__main__':
main()
Output:
Executing our Task = 1 and A
Executing our Task = 2 and B
MainThread: tasks submitted
Task Executed <Thread(ThreadPoolExecutor-0_0, started daemon 12192)>
Task Executed <Thread(ThreadPoolExecutor-0_1, started daemon 11800)>