如何在另一个asyncio循环中使用asyncio循环

ant*_*s87 7 python asynchronous python-3.x python-asyncio

我一直在尝试各种各样的东西,以便能够在另一个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)
Run Code Online (Sandbox Code Playgroud)

use*_*342 8

运行loop.run_until_compete一个正在运行的事件循环内将阻止外循环,从而挫败使用ASYNCIO的目的.因此,asyncio事件循环不是递归的,并且不应该递归地运行它们.而不是创建内部事件循环,await而是在现有循环上创建任务.

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

images = sub_run(other_data)
Run Code Online (Sandbox Code Playgroud)

有:

images = await sub_build(other_data)
Run Code Online (Sandbox Code Playgroud)

并且它可以正常工作,运行子协同程序,而不是继续使用外部协程,直到内部协程完成,正如您可能从同步代码中所预期的那样.

  • 太棒了!我现在明白了!我可以使用相同的循环并为该循环创建更多任务.你非常清楚地解释了它,非常感谢你. (2认同)