【问题标题】:python async function inside an async function异步函数中的python异步函数
【发布时间】:2021-04-23 09:34:07
【问题描述】:

我的代码:

import asyncio
from random import randrange

async def inner_sleep(letter, num):
    print(f'start inner sleep {letter}, {num}')
    myint = randrange(5)
    await asyncio.sleep(myint)
    print(f'done with inner sleep {letter}, {num}')

async def outer_sleep(letter):
    print(f'start outer sleep {letter}')
    myint = randrange(5)
    await asyncio.sleep(myint)
    print(f'done with outer sleep {letter}')

async def inside(letter):
    nums = [1,2,3,4,5,6]
    tasks = []

    async def create_task(num):
        task = asyncio.ensure_future(inner_sleep(letter, num))
        tasks.append(task)
    
    for num in nums:
        await create_task(num)

    await asyncio.gather(*tasks)


async def outside():

    letters = ['a','b','c','d']
    tasks = []

    async def create_task_1(letter):
        task = asyncio.ensure_future(outer_sleep(letter))
        tasks.append(task)

    for letter in letters:
        await create_task_1(letter)
        await inside(letter)
    
    await asyncio.gather(*tasks)

asyncio.run(outside())

样本输出:

start outer sleep a
start inner sleep a, 1
start inner sleep a, 2
start inner sleep a, 3
start inner sleep a, 4
start inner sleep a, 5
start inner sleep a, 6
done with inner sleep a, 4
done with outer sleep a
done with inner sleep a, 2
done with inner sleep a, 3
done with inner sleep a, 1
done with inner sleep a, 5
done with inner sleep a, 6
start outer sleep b
start inner sleep b, 1
start inner sleep b, 2
start inner sleep b, 3
start inner sleep b, 4
start inner sleep b, 5
start inner sleep b, 6
done with inner sleep b, 3
done with inner sleep b, 5
done with inner sleep b, 4
done with outer sleep b
done with inner sleep b, 1
done with inner sleep b, 6
done with inner sleep b, 2
start outer sleep c
start inner sleep c, 1

我在循环中有一个循环,我希望它们都异步运行。内部的工作正常,但我无法让外部的人做我想做的事。在上面的代码中,我希望我的外部函数同时循环遍历列表“字母”。对于每个字母,我需要在第二个函数 (inner_sleep) 开始之前完成第一个函数 (outer_sleep)。我似乎找不到放置内部功能的地方来完成此操作。当我运行此代码时,您可以在结果中看到“内部睡眠 a”是如何在“完成外部睡眠 a”之前开始的。理想情况下,我的输出如下所示:

start outer sleep a
start outer sleep b
finish outer sleep a
start inner sleep a, 1
start inner sleep a, 2
start inner sleep a, 3
start inner sleep a, 4
start inner sleep a, 5
start inner sleep a, 6
finish outer sleep b
start inner sleep b, 1
start inner sleep b, 2
start inner sleep b, 3
start inner sleep b, 4
start inner sleep b, 5
start inner sleep b, 6
done with inner sleep a, 4
done with inner sleep a, 2
done with inner sleep b, 3

这可能吗?

【问题讨论】:

    标签: python python-asyncio


    【解决方案1】:

    create_task_1 中,您正在调用outer_sleep,但您没有await 结果。这意味着任务已启动,但outside 函数的执行在完成之前继续进行。

    您有需要create_task_1 函数的原因吗?你可以直接await outer_sleep(letter)吗?例如(注意这是未经测试的):

    async def outside():
    
        letters = ['a','b','c','d']
        
        # don't need create_task_1 funciton anymore
    
        for letter in letters:
            await outer_sleep(letter)
            await inside(letter)
        
        # don't need to gather the tasks as they're already complete
    

    编辑

    您在 cmets 中阐明您希望所有 outer_sleep 任务同时启动。你只需要稍微翻转一下执行顺序

    async def outside():
    
        letters = ['a','b','c','d']
        tasks = []
    
        async def task_1(letter):
            await outer_sleep(letter)
            await inside(letter)
    
        for letter in letters:
            task = asyncio.ensure_future(task_1(letter))
            tasks.append(task)
        
        await asyncio.gather(*tasks)
    

    【讨论】:

    • 这确实有助于确保outer_sleep 在inner_sleep 之前完成,但是它也不会使通过字母的循环也异步。我想通过字母收集整个循环,这样当它等待'a'的outer_sleep函数时,它可以继续为'b'启动outer_sleep。
    • 你无法通过 for 循环真正实现这一点。你需要像asyncio.gather 这样的东西。
    【解决方案2】:

    await inside(letter) 放在outer_sleep 的末尾怎么样?这确保了它只会在特定outer_sleep 的结果到达时运行。

    import asyncio
    from random import randrange
    
    
    async def inner_sleep(letter, num):
        print(f'start inner sleep {letter}, {num}')
        myint = randrange(5)
        await asyncio.sleep(myint)
        print(f'done with inner sleep {letter}, {num}')
    
    
    async def inside(letter):
        nums = [1, 2, 3, 4, 5, 6]
        tasks = [asyncio.ensure_future(inner_sleep(letter, num)) for num in nums]
        await asyncio.gather(*tasks)
    
    
    async def outer_sleep(letter):
        print(f'start outer sleep {letter}')
        myint = randrange(5)
        await asyncio.sleep(myint)
        print(f'done with outer sleep {letter}')
        await inside(letter)
    
    
    async def outside():
        letters = ['a', 'b', 'c', 'd']
        tasks = [asyncio.ensure_future(outer_sleep(letter)) for letter in letters]
        await asyncio.gather(*tasks)
    
    
    asyncio.run(outside())
    

    asyncio.gather 表示数字和字母都可以按任何顺序处理(例如,“c”可以在“b”之前),如果您可以的话。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 2021-12-25
      • 2022-11-16
      • 1970-01-01
      • 2019-01-20
      • 2020-10-25
      相关资源
      最近更新 更多