簡體   English   中英

如何等待Python asyncio call_later完成所有未決

[英]How to wait for Python asyncio call_later to finish all pending

我想編寫一個程序,該程序利用call_later來發信號通知某事(或事物)稍后發生,它們本身可能會添加更多要調用的例程,然后發信號通知該程序運行,直到沒有剩余要運行的東西為止。 例如,我可以執行以下操作:

import  asyncio
START_RATE = 1

async def say_hi(who):
    print(f'hello {who}')

async def call_later(t, func, *params):
    await asyncio.sleep(t)
    await func(*params)

def run():
    # Let's go!
    incr = START_RATE
    loop = asyncio.get_event_loop()
    tasks = []
    for x in range(5):
        wait_delta = 5 - x
        tasks.append(
            call_later(incr * wait_delta, say_hi, x)
        )

    loop.run_until_complete(asyncio.gather(*tasks))

run()

但是您會注意到call_later是定制的協程。

是否可以使用事件循環的call_later ,但是以某種方式檢查事件循環或以其他方式等待所有未完成的回調的完成?

您可能會使用asyncio.all_tasks()進行內省,但這可能是錯誤的方法。

正確的方法是創建期貨並允許call_later將其標記為已完成:

import asyncio
from functools import partial
START_RATE = 1


def say_hi(who):
    print(f'hello {who}')


def run_on_finish(callback):
    def wrapper(func, *args, **kwargs):
        try:
            return func(*args, **kwargs)
        finally:
            callback()
    return wrapper


def release_waiter(waiter, *args):
    """Taken from standard library"""
    if not waiter.done():
        waiter.set_result(None)


def run():
    # Let's go!
    incr = START_RATE
    loop = asyncio.get_event_loop()
    tasks = []
    for x in range(5):
        wait_delta = 5 - x

        # Create a waiter
        waiter = loop.create_future()
        release_cb = partial(release_waiter, waiter)

        # Schedule the function, making sure we release the waiter on finish
        handle = loop.call_later(incr * wait_delta, run_on_finish(release_cb),
                                 say_hi, x)

        # If waiter is cancelled, cancel the handle too.
        waiter.add_done_callback(lambda *args: handle.cancel)

        tasks.append(waiter)

    loop.run_until_complete(asyncio.gather(*tasks))


run()

請記住, call_later用於常規功能而非協程。 如果say_hi需要成為協程,則應在混合中添加ensure_futureloop.create_task

如果把它們也確實會帶來更多的並發症-你需要添加更多的功能,從而利用ensure_future的產生的未來,並用類似的方式,以你的服務員IT連鎖futures._chain_future

我已經強烈建議您在這種情況下使用自己的協程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM