Python:Concurrent.Futures错误[TypeError:'NoneType'对象不可调用]

3
我设法让asyncio / Google CSE API共同运行....在PyCharm上运行代码时,我能够输出结果。然而,在打印的结果的最后面,出现了错误“TypeError:'NoneType'对象不可调用”。
我怀疑这与我的列表有关,也许是循环试图搜索另一个术语,即使我已经到了列表的末尾...
还有...这是我第一次发问,请随意提供如何更好地提问的建议
你有什么想法吗?
searchterms = ['cheese',
    'hippos',
    'whales',
    'beluga']

async def sendQueries(queries, deposit=list()):
    with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
        loop = asyncio.get_event_loop()
        futures = [
            loop.run_in_executor(
                executor,
                searching(queries)
            )
        ]
        for response in await asyncio.gather(*futures):
            deposit.append(response.json())
        return deposit

def running():
     loop = asyncio.get_event_loop()
     loop.run_until_complete(loop.create_task(sendQueries(searchterms)))
     loop.close()

print(running())
print(str(time.time() - x))

我的错误可以追溯到"for response in await asyncio.gather(*futures):"。

供您参考,搜索(queries)只是我调用Google CSE API的函数。


无关的提示:你应该阅读有关可变默认参数的内容。你可能会在deposit中遇到问题。 - dirn
2个回答

6
问题出现在对run_in_executor的调用中:
    futures = [
        loop.run_in_executor(
            executor,
            searching(queries)
        )
    ]

run_in_executor接受要执行的函数。代码没有将函数传递给它,而是调用一个名为searching的函数,并将该调用的返回值传递给run_in_executor。这有两个后果:

  1. 代码无法按预期工作-它一个接一个地调用搜索,而不是并行执行;

  2. 它显示了一个错误,抱怨run_in_executor尝试调用searching(...)None返回值。令人困惑的是,只有在稍后等待run_in_executor返回的futures时才会引发错误,而此时所有搜索实际上都已完成。

正确的调用run_in_executor的方法应该像这样:

    futures = [
        loop.run_in_executor(executor, searching, queries)
    ]

请注意,现在仅提到了 searching 函数,而不是使用它。
此外,如果你只是使用 asyncio 在 run_in_executor 中调用同步调用,那么你并没有真正从中受益。你可以直接使用基于线程的工具从 concurrent.futures 获取相同的效果,但无需调整整个程序以适应 asyncio。 run_in_executor 应该被节约地使用,即要么偶尔与不提供异步前端的传统 API 进行交互,要么用于不能有意义地转换为协程的 CPU 重负载代码。

好的。感谢帮忙。现在它的速度明显变快了。我能够在1.1秒内得到约12个搜索实例,而不是之前的5个。之前的时间确实有些可疑...... - Isaac Lau
太棒了!即使我使用了 with ThreadPoolExecutor as exe: exe.submit,它也解决了我的问题。 - Jonathan

2

我使用executor.submit()也遇到了相同的错误

# not work
futures.append(executor.submit(myfunc(arg1, arg2)))

# works
futures.append(executor.submit(myfunc, arg1, arg2))

Thank you guys,


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接