如何在 python 3.5 中使对象可等待?
Posted
技术标签:
【中文标题】如何在 python 3.5 中使对象可等待?【英文标题】:How to make object awaitable in python 3.5? 【发布时间】:2017-05-31 12:01:47 【问题描述】:我有一个伪异步生成器,它实际上在初始化时获取所有需要的数据。我想用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__
方法并且看起来这个方法应该返回迭代器对象,但是我怎样才能为实际上不可迭代的对象创建迭代器?
【问题讨论】:
return = [MakeObject() for i in make_http_request()]
导致 SyntaxError
请提供所有代码 (minimal, complete and verifiable example)。
总是提出问题完整的错误信息。
我更新了问题,谢谢你的cmets。
如果你只需要发出http请求,请使用aiohttp
【参考方案1】:
__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')
【讨论】:
以上是关于如何在 python 3.5 中使对象可等待?的主要内容,如果未能解决你的问题,请参考以下文章
python - 如何在python中使没有簇质心的簇不可见?
如何在 Cloud Functions for Firebase 中使 HTTP 请求异步/等待?