【问题标题】:Check if asyncio shielded coroutine ran检查异步屏蔽协程是否运行
【发布时间】:2018-08-22 00:06:44
【问题描述】:

如果我有以下代码示例

async def coro():
    # Cancelled error could be raised here
    await asyncio.sleep(1)
    # Or here
    await asyncio.shield(
        another_coro()
    )
    # Or here

async def wait_on_it(loop):
    f = loop.create_task(coro())
    # Pretend f may or may not happen, I just sleep in this example
    await asyncio.sleep(1)
    if not f.done():
        f.cancel() # Will raise CancelledError when some await finishes in coro()

如何确定屏蔽任务是否实际运行?如果屏蔽任务确实运行,我有必须运行的重要逻辑。也许屏蔽那个功能不是正确的方法?

【问题讨论】:

    标签: python-3.x python-asyncio


    【解决方案1】:

    coro() 可以通过修改从调用者那里接收到的可变对象将信息传递给调用者:

    class Ref:
        def __init__(self, **kwargs):
            self.__dict__.update(**kwargs)
    
    async def coro(run_ref):
        await asyncio.sleep(1)
        run_ref.ran_another_coro = True
        await asyncio.shield(another_coro())
    
    async def wait_on_it(loop):
        run_ref = Ref(ran_another_coro=False)
        f = loop.create_task(coro(run_ref))
        await asyncio.sleep(1)
        if not f.done():
            f.cancel()
        if run_ref.ran_another_coro:
             # ... another_coro() was started
    

    由于asyncio.shield 无法挂起,如果wait_on_it 观察到run_ref.ran_another_coro 的真值,则保证another_coro() 已启动。

    【讨论】:

    • 你定义类Ref而不是简单地使用布尔值有什么原因吗?
    • @shane 是的,bool 是不可变的。在函数内分配给bool 只会修改局部变量,而不是调用者中的变量。另一方面,分配给调用者提供的可变对象的插槽将更改对象,coro() 及其调用者都可以看到。
    猜你喜欢
    • 1970-01-01
    • 2015-11-26
    • 1970-01-01
    • 2012-02-20
    • 2015-06-02
    • 1970-01-01
    • 2023-04-08
    • 2015-11-12
    • 1970-01-01
    相关资源
    最近更新 更多