异步迭代器定期滴答

时间:2017-10-25 13:41:47

标签: python python-3.x asynchronous python-asyncio

我正在实现一个与async for一起使用的异步迭代器,它应该以(大部分)常规间隔返回一个新值。

我们可以用一个简单的时钟来说明这样的迭代器,它会每隔~n秒递增一个计数器:

import asyncio

class Clock(object):
    def __init__(self, interval=1):
        self.counter = 0
        self.interval = interval
        self.tick = asyncio.Event()
        asyncio.ensure_future(self.tick_tock())

    async def tick_tock(self):
        while True:
            self.tick.clear()
            await asyncio.sleep(self.interval)
            self.counter = self.__next__()
            self.tick.set()

    def __next__(self):
        self.counter += 1
        return self.counter

    def __aiter__(self):
        return self

    async def __anext__(self):
        await self.tick.wait()
        return self.counter

是否有比使用asyncio.Event更好或更清洁的方法?

这个迭代器上有多个协程async for

2 个答案:

答案 0 :(得分:1)

在我看来,你的方法很好。请注意,从python 3.6开始,您还可以使用asynchronous generators

async def clock(start=0, step=1, interval=1.):
    for i in count(start, step):
        yield i
        await asyncio.sleep(interval)

但是,您无法在多个协同程序之间共享它们。您必须在任务中运行时钟并通过异步迭代接口使数据可用,这基本上就是您在代码中所做的。这是possible implementation

答案 1 :(得分:0)

如果您使用的是Python 3.6+,则可以使用更具可读性的asynchronous generators

async def Clock(interval=1):
    counter = 0
    while True:
        await asyncio.sleep(interval)
        counter += 1
        yield counter


async def main():
    async for i in Clock(1):
        print(i)
        if i == 4:
            break


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(main())
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.close()