ThreadPoolExecutor.submit执行异常求助:非线程环境无此问题
TypeError: 'str' object is not callable 你遇到的问题核心是对executor.submit()的用法理解有误,我们一步步拆解原因:
关键错误点
先看你线程池代码里的这一行:
cats_results = [executor.submit(i.sayname()) for i in cats]
这里你犯了一个非常典型的新手误区:你直接调用了i.sayname(),把方法执行后的字符串结果传给了submit(),而不是把方法本身作为可调用对象传递。
为什么会触发异常?
executor.submit()的第一个参数要求是一个可调用对象(比如函数、类方法、lambda表达式等),线程池会在后续的线程中调用这个对象。但你这里的i.sayname()会立即执行,返回的是"Miaw, xxx"这样的字符串——相当于你给线程池塞了一个字符串当任务,而字符串显然不是可调用的,所以线程在尝试执行任务时就会抛出TypeError: 'str' object is not callable。
而你不用线程池的代码里,[i.sayname() for i in cats]是直接在主线程中执行方法,得到字符串列表,这当然没问题,因为这里不需要把方法交给其他执行器去调用。
修正后的代码
只需要去掉sayname后面的括号,把方法本身传递给submit()即可(实例方法本身就是可调用对象,线程池会自动帮你调用它):
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] # 调用result()方法获取异步任务的返回值(注意是方法调用,不是属性访问) print([i.result() for i in cats_results]) main()
运行结果
执行修正后的代码会输出:
['Miaw, Sprinkles', 'Miaw, Button', 'Miaw, Fluffy', 'Miaw, Semla']
和你不用线程池的代码结果完全一致。
另外补充:你之前写的print([i.result for i in cats_results])只是打印了Future对象的result方法的绑定对象,并没有真正获取任务结果,所以才会看到一堆<bound method Future.result...>的输出,正确的做法是调用i.result()来获取异步任务的返回值。
内容的提问来源于stack exchange,提问作者compuTE

