gpt4 book ai didi

python-3.x - 为什么协程不能与 run_in_executor 一起使用?

转载 作者:行者123 更新时间:2023-12-01 16:48:21 24 4
gpt4 key购买 nike

我想运行一个使用协程和多线程请求 URL 的服务。但是我无法将协程传递给执行器中的工作人员。有关此问题的最小示例,请参阅下面的代码:

import time
import asyncio
import concurrent.futures

EXECUTOR = concurrent.futures.ThreadPoolExecutor(max_workers=5)

async def async_request(loop):
await asyncio.sleep(3)

def sync_request(_):
time.sleep(3)

async def main(loop):
futures = [loop.run_in_executor(EXECUTOR, async_request,loop)
for x in range(10)]

await asyncio.wait(futures)

loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))

导致以下错误:

Traceback (most recent call last):
File "co_test.py", line 17, in <module>
loop.run_until_complete(main(loop))
File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
return future.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
raise self._exception
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "co_test.py", line 10, in main
futures = [loop.run_in_executor(EXECUTOR, req,loop) for x in range(10)]
File "co_test.py", line 10, in <listcomp>
futures = [loop.run_in_executor(EXECUTOR, req,loop) for x in range(10)]
File "/usr/lib/python3.5/asyncio/base_events.py", line 541, in run_in_executor
raise TypeError("coroutines cannot be used with run_in_executor()")
TypeError: coroutines cannot be used with run_in_executor()

我知道我可以使用sync_request函数而不是async_request,在这种情况下,我可以通过将阻塞函数发送到另一个线程来拥有协程。

我还知道我可以在事件循环中调用 async_request 十次。类似于下面的代码:

loop = asyncio.get_event_loop()
futures = [async_request(loop) for i in range(10)]
loop.run_until_complete(asyncio.wait(futures))

但在这种情况下我将使用单个线程。

我如何使用这两种场景,即在多线程中工作的协程?正如您在代码中看到的,我将 pool 传递(而不是使用)到 async_request,希望我可以编写一些代码来告诉工作人员创建一个 future ,将其发送到池中并异步(释放工作线程)等待结果。

我想这样做的原因是为了使应用程序具有可扩展性。这是一个不必要的步骤吗?我是否应该简单地为每个网址设置一个线程,仅此而已?像这样的东西:

LEN = len(list_of_urls)
EXECUTOR = concurrent.futures.ThreadPoolExecutor(max_workers=LEN)

足够好了吗?

最佳答案

您必须在线程上下文中创建并设置一个新的事件循环才能运行协程:

import asyncio
from concurrent.futures import ThreadPoolExecutor


def run(corofn, *args):
loop = asyncio.new_event_loop()
try:
coro = corofn(*args)
asyncio.set_event_loop(loop)
return loop.run_until_complete(coro)
finally:
loop.close()


async def main():
loop = asyncio.get_event_loop()
executor = ThreadPoolExecutor(max_workers=5)
futures = [
loop.run_in_executor(executor, run, asyncio.sleep, 1, x)
for x in range(10)]
print(await asyncio.gather(*futures))
# Prints: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

关于python-3.x - 为什么协程不能与 run_in_executor 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46074841/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com