如何在异步协程中包装同步函数?
我使用aiohttp来构建一个将TCP请求发送到单独服务器的API服务器。发送TCP请求的模块是同步的,并且是我的目的的黑盒子。所以我的问题是这些请求阻止了整个API。我需要一种将模块请求封装在异步协程中的方法,该协议不会阻塞其余的API。如何在异步协程中包装同步函数?
所以,仅仅用sleep
作为一个简单的例子,有没有办法以某种方式包裹在无阻塞协程耗时同步码,这样的事情:
async def sleep_async(delay):
# After calling sleep, loop should be released until sleep is done
yield sleep(delay)
return 'I slept asynchronously'
最终我找到了答案this thread。我正在寻找的方法是run_in_executor。这允许异步运行同步功能而不阻塞事件循环。
在sleep
例子我张贴以上,这可能是这样的:
import asyncio
from time import sleep
from concurrent.futures import ProcessPoolExecutor
async def sleep_async(loop, delay):
# Can set executor to None if a default has been set for loop
await loop.run_in_executor(ProcessPoolExecutor(), sleep, delay)
return 'I slept asynchronously'
另请参阅下面的答案 - >How do we call a normal function where a coroutine is expected?
'ProcessPoolExecutor'成本高,因为它启动了一个全新的python解释器。当您需要使用多个处理器的CPU密集型任务时使用它。考虑使用'ThreadPoolExecutor',而不是使用线程。 – Oleg
感谢您的额外信息。虽然最初的例子使用了进程池,但是ThreadPoolExecutor是我在经过多一点研究之后最终使用的。看起来还是有些狡猾,但到目前为止,它们都在一起。 –
请注意,不是创建一个新的执行程序,而是通过调用'loop.run_in_executor(executor = None,func,* args)'来使用默认执行程序可能会更简单一些(参见[documentation](https:// docs。 python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_in_executor))。 –
你总是在I/O块。通过合作性多任务处理,您无法获得所需的行为,因为阻止的协同程序仅在请求完成后才返回控制(收益)。 –
aiohttp适用于http。对于非http TCP,asyncio就足够了。 – Udi