码迷,mamicode.com
首页 > 其他好文 > 详细

asyncio时间循环中运行阻塞任务

时间:2020-04-01 22:08:32      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:官方文档   函数   文档   llb   loop   执行   turn   UNC   lib   

 场景:

在某个异步循环中 需要执行某个阻塞任务(例如文件读写., 保存图片等)

如果这个时候直接在异步事件循环中直接运行, 那么所有任务都会阻塞在这里, 明显是不行的

 

解决方案:

https://docs.python.org/3/library/asyncio-eventloop.html#executing-code-in-thread-or-process-pools

 

import concurrent.futures

def blocking_io():
    # File operations (such as logging) can block the
    # event loop: run them in a thread pool.
    with open(/dev/urandom, rb) as f:
        return f.read(100)

# 在某个异步事件循环中
async def main():
    loop = asyncio.get_running_loop()  # 获取当前事件循环

    result = await loop.run_in_executor(None, blocking_io)

    with concurrent.futures.ThreadPoolExecutor() as pool:
          result = await loop.run_in_executor(
            pool, blocking_io)
          print(custom thread pool, result)

asyncio.run(main())

 

loop.run_in_exeutor(pool, func)

pool为线程池 在python里面为concurrent.futures.ThreadPoolExecutor的实例

func为需要运行的同步函数 如果需要传入参数, 要用functools.partial(func, *arg, **kwargs)  传入.

 

运行之后, 则会在不阻塞异步时间循环的情况下 ,在新的线程中运行func 结束之后用await接收

 

如果一开始不指定线程池,那么官方文档中说的是默认线程池

这里的默认线程池可以用

loop.set_default_executor(executor)

来指定

如果一开始也不指定, 那么经过阅读源码之后 可知:

    def run_in_executor(self, executor, func, *args):
        self._check_closed()
        if self._debug:
            self._check_callback(func, run_in_executor)
        if executor is None:
            executor = self._default_executor
            if executor is None:
                executor = concurrent.futures.ThreadPoolExecutor()
                self._default_executor = executor
        return futures.wrap_future(
            executor.submit(func, *args), loop=self)

他会帮我们自动启用一个线程池, 丢进去运行.

 

总之异步的时间循环中如果要加入阻塞型代码,  千万不能直接阻塞, 用此法可破.

asyncio时间循环中运行阻塞任务

标签:官方文档   函数   文档   llb   loop   执行   turn   UNC   lib   

原文地址:https://www.cnblogs.com/btxlc/p/12616288.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!