Search code examples
pythonmultithreadingthreadpoolexecutorconcurrent.futures

ThreadPoolExecutor executor.submit() returns an exception which is not raised without it


I have noticed that the result() function of a ThreadPoolExecutor is not behaving as i expect. It returns an exception that is not raised without the threads.

Here is a reproducible, minimal example:

import concurrent.futures
import time
class cat:
    def __init__(self, name=""):
        self.name = name
    def sayname(self):
        return("Miaw, " + self.name)

def main():
     names = ["Sprinkles", "Button", "Fluffy", "Semla"]
     cats = [cat(name = i) for i in names]
     with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
         cats_results = [executor.submit(i.sayname()) for i in cats]
     print([i.result for i in cats_results])

main()

Returns (notice the TypeError):

[<bound method Future.result of <Future at 0x7f227e3259d0 state=finished raised TypeError>>,
<bound method Future.result of <Future at 0x7f227e325c50 state=finished raised TypeError>>, 
<bound method Future.result of <Future at 0x7f227e325f50 state=finished raised TypeError>>, 
<bound method Future.result of <Future at 0x7f227e330290 state=finished raised TypeError>>, 
<bound method Future.result of <Future at 0x7f227e330590 state=finished raised TypeError>>]

This of course is without actually calling results, but if i change print([i.result for i in cats_results]) to print([i.result() for i in cats_results]) it returns:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in main
  File "/usr/lib/python2.7/site-packages/concurrent/futures/_base.py", line 422, in result
    return self.__get_result()
  File "/usr/lib/python2.7/site-packages/concurrent/futures/thread.py", line 62, in run
    result = self.fn(*self.args, **self.kwargs)
TypeError: 'str' object is not callable

But if I do:

def main():
     names = ["Sprinkles", "Button", "Fluffy", "Semla"]
     cats = [cat(name = i) for i in names]
     cats_results = [i.sayname() for i in cats]
     print([i for i in cats_results])

It returns no problem with:

['Miaw, Sprinkles', 'Miaw, Button', 'Miaw, Fluffy', 'Miaw, Semla']

Any idea on what is happening with executor.submit?

(I'm using python 3.6.6)


Solution

  • It looks like typos, after a few corrections everything works:

    import concurrent.futures
    import time
    
    
    class cat:
        def __init__(self, name=""):
            self.name = name
    
        def sayname(self):
            return ("Miaw, " + self.name)
    
    
    def main():
        names = ["Sprinkles", "Button", "Fluffy", "Semla"]
        cats = [cat(name=i) for i in names]
        with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
            cats_results = [executor.submit(i.sayname) for i in cats]
        print([i.result() for i in cats_results])
    
    
    main()