2017-01-16 1 views
1

나는 초기화에 필요한 모든 데이터를 실제로 가져 오는 의사 비동기 생성기가 있습니다. 그리고 async for으로 반복하고 싶습니다. 내 간단한 코드는 다음과 같습니다 : 나는 async for x in MyGenerator()이 코드를 실행하면, 내가 "TypeError: 'async for' received an invalid object from __anext__: MyObject"을 얻을 것이다어떻게 파이썬 3.5에서 객체를 기다릴 수 있습니까?

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 

.

비동기 생성기가 대기 가능한 객체를 반환해야합니다. 그래서 질문은 - "고전적인"객체를 어떻게 기다릴 수 있습니까? 마치 __await__ 메서드를 구현해야하며이 메서드가 반복자 개체를 반환해야하는 것처럼 보입니다. 그러나 실제로 반복 가능한 개체가 아닌 반복자를 만들 수 있습니까?

+2

'반환 = [MakeObject() 나는() make_http_request에 대한] 구문 에러 – falsetru

+0

'원인 제공하십시오 ** 모든 ** 코드 ([최소한의 완전하고 검증 가능한 예제] (https://stackoverflow.com/help/mcve)). –

+0

항상 전체 오류 메시지를 넣습니다. – furas

답변

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') 
관련 문제