我有一个伪异步生成器,它实际上在初始化时获取所有需要的数据。我想用async for
迭代它。我的简化代码如下所示:
class MyObject:
def __init__(self, name):
self.name
def operate(self):
pass
class MyGenerator:
def __init__(self, params):
self.params = params
self.current = 0
self.last = None
self.data = None
async def make_http_request(self):
await asyncio.sleep(1)
return 42
async def fetch_data(self):
# actually it is not comprehentions since async comprehentions
# are not available in 3.5. It is a simple loop with await's
return [MyObject(i) for i in self.make_http_request()]
def __aiter__(self):
self.data = await self.fetch_data()
return self
def __anext__(self):
try:
result = self.data[self.current]
except IndexError:
raise StopAsyncIteration
self.current += 1
return result
如果我使用async for x in MyGenerator()
运行此代码,我将获得"TypeError: 'async for' received an invalid object from __anext__: MyObject"
。
所以看起来异步生成器应该返回等待对象。所以问题是 - 我怎样才能使“经典”物体等待?看起来我应该实现__await__
方法,看起来这个方法应该返回迭代器对象,但是如何为实际上不可迭代的对象创建迭代器呢?
答案 0 :(得分:0)
__anext__
"Must return an awaitable"。目前它将返回MyObject()
。我已经更改了下面的self.fetch_data()
- 请查看此示例以演示异步运行的3个生成器:
import asyncio
import random
class MyGenerator:
async def make_http_request(self):
n = random.uniform(0.1, 3)
await asyncio.sleep(n)
return n
def fetch_data(self):
return [self.make_http_request() for i in range(5)]
def __aiter__(self):
self.current = 0
self.data = self.fetch_data()
return self
def __anext__(self):
# print("anext")
try:
task = self.data[self.current]
except IndexError:
raise StopAsyncIteration
self.current += 1
return task
async def main(tag):
print(tag, "start")
async for x in MyGenerator():
print(tag, x)
print(tag, "done")
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(main("A"), main("B"), main("C")))
loop.close()
print('done')