【问题标题】:How to wait for object to change state如何等待对象改变状态
【发布时间】:2017-12-07 02:06:29
【问题描述】:

在我的async 处理程序中,我想等到任务的状态发生变化。现在,我只是在无限循环中检查状态并等待。下面是一个例子,wait_until_done 函数:

import asyncio


class LongTask:
    state = 'PENDING'

my_task = LongTask()


def done():
    my_task.state = 'DONE'

async def wait_until_done():
    while True:
        if my_task.state == 'PENDING':
            await asyncio.sleep(2)
        else:
            break
    print("Finally, the task is done")


def main(loop, *args, **kwargs):
    asyncio.ensure_future(wait_until_done())
    loop.call_later(delay=5, callback=done)

loop = asyncio.get_event_loop()
main(loop)
loop.run_forever()

有没有更好的方法来做到这一点?

【问题讨论】:

  • 观察者模式可能是您想要使用的。使对象“可观察”,然后将处理程序注册为对象的观察者,因此当状态更改时,它将调用您想要的任何方法。 stackoverflow.com/questions/1904351/…

标签: python python-3.5 python-asyncio


【解决方案1】:

为了避免混淆:我猜你说的不是asyncio.Task,而是一些变量状态,对吧?

在这种情况下,您有 Futuresynchronization primitives 允许您等待异步更改的某些内容。

如果你需要在两种状态之间切换,asyncio.Event 可能就是你想要的。这是一个小例子:

import asyncio


my_task = asyncio.Event()


def done():
    my_task.set()



async def wait_until_done():
    await my_task.wait()  # await until event would be .set()
    print("Finally, the task is done")


async def main():
    loop.call_later(delay=5, callback=done)
    await wait_until_done()


loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

更新:

保持LongTask接口的更复杂的例子:

import asyncio



class LongTask:
    _event = asyncio.Event()

    @property
    def state(self):
        return 'PENDING' if not type(self)._event.is_set() else 'DONE'

    @state.setter
    def state(self, val):
        if val == 'PENDING':
            type(self)._event.clear()
        elif val == 'DONE':
            type(self)._event.set()
        else:
            raise ValueError('Bad state value.')

    async def is_done(self):
        return (await type(self)._event.wait())

my_task = LongTask()


def done():
    my_task.state = 'DONE'



async def wait_until_done():
    await my_task.is_done()
    print("Finally, the task is done")


async def main():
    loop.call_later(delay=5, callback=done)
    await wait_until_done()


loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

【讨论】:

  • 是的,任务是一个常规对象,不是 asyncio.Task。我考虑了 Event(),但您的解决方案不适合:长话短说,我无法触摸 done 函数,它应该只是改变任务的状态。
  • @SergeyBelash,我添加了另一个保持done func 不变的示例。
猜你喜欢
  • 2019-03-16
  • 1970-01-01
  • 1970-01-01
  • 2022-07-15
  • 1970-01-01
  • 1970-01-01
  • 2020-02-25
  • 2017-12-16
  • 1970-01-01
相关资源
最近更新 更多