代码之家  ›  专栏  ›  技术社区  ›  antfuentes87

如何在另一个异步IO循环中使用异步IO循环

  •  15
  • antfuentes87  · 技术社区  · 6 年前

    我一直在尝试各种方法,以便能够在另一个asyncio循环中使用asyncio循环。大多数情况下,我的测试以错误告终,例如:

    RuntimeError:此事件循环已在运行

    下面的示例代码只是我开始的基本测试,因此您可以看到我正在尝试执行的基本操作。在这次测试之后,我尝试了很多东西,只是太混乱了,所以我想在寻求帮助时应该保持简单。如果有人能给我指出正确的方向,那就太好了。感谢您抽出时间!

    import asyncio
    
    async def fetch(data):
        message = 'Hey {}!'.format(data)
        other_data = ['image_a.com', 'image_b.com', 'image_c.com']
        images = sub_run(other_data)
        return {'message' : message, 'images' : images}
    
    async def bound(sem, data):
        async with sem:
            r = await fetch(data)
            return r
    
    async def build(dataset):
        tasks = []
        sem = asyncio.Semaphore(400)
    
        for data in dataset:
            task = asyncio.ensure_future(bound(sem, data))
            tasks.append(task)
    
        r = await asyncio.gather(*tasks)
        return r
    
    def run(dataset):
        loop = asyncio.get_event_loop()
        future = asyncio.ensure_future(build(dataset))
        responses = loop.run_until_complete(future)
        loop.close()
        return responses
    
    async def sub_fetch(data):
        image = 'https://{}'.format(data)
        return image
    
    async def sub_bound(sem, data):
        async with sem:
            r = await sub_fetch(data)
            return r
    
    async def sub_build(dataset):
        tasks = []
        sem = asyncio.Semaphore(400)
    
        for data in dataset:
            task = asyncio.ensure_future(sub_bound(sem, data))
            tasks.append(task)
    
        r = await asyncio.gather(*tasks)
        return r
    
    def sub_run(dataset):
        loop = asyncio.get_event_loop()
        future = asyncio.ensure_future(sub_build(dataset))
        responses = loop.run_until_complete(future)
        loop.close()
        return responses
    
    if __name__ == '__main__':
        dataset = ['Joe', 'Bob', 'Zoe', 'Howard']
        responses = run(dataset)
        print (responses)
    
    1 回复  |  直到 6 年前
        1
  •  14
  •   user4815162342    6 年前

    跑步 loop.run_until_compete 运行中的事件循环内部会阻塞外部循环,因此无法达到使用asyncio的目的。因此,异步IO事件循环不是递归的,不需要递归地运行它们。而不是创建内部事件循环, await 现有任务上的任务。

    在您的情况下,请删除 sub_run 并简单地替换其用法:

    images = sub_run(other_data)
    

    使用:

    images = await sub_build(other_data)
    

    它将很好地工作,运行子协同路由,在内部协同路由完成之前不继续执行外部协同路由,就像您在同步代码中所期望的那样。