异步迭代器定期滴答
Async iterator ticking at a regular interval
我正在实现一个与 async for
一起使用的异步迭代器,它应该 return 一个(大部分)固定间隔的新值。
我们可以用一个简单的时钟来说明这样的迭代器,它每 ~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
在这个迭代器上。
如果您使用的是 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()
在我看来,你的做法很好。请注意,自 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.
我正在实现一个与 async for
一起使用的异步迭代器,它应该 return 一个(大部分)固定间隔的新值。
我们可以用一个简单的时钟来说明这样的迭代器,它每 ~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
在这个迭代器上。
如果您使用的是 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()
在我看来,你的做法很好。请注意,自 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.