2016-07-02 1 views
2

정말 멋지게 보이는 asynch로 실험하기 시작했습니다. 영원히 실행되는 비동기의 동시 루틴과 함께 미래를 사용하기 위해 노력하고있어하지만 난이 오류를 얻을 :loop_forever와 함께 미래를 사용하는 파이썬

import asyncio 

@asyncio.coroutine 
def slow_operation(): 
    yield from asyncio.sleep(1) 
    print ("This is the task!") 
    future.set_result('This is the future!') 
    asyncio.async(slow_operation()) 

def got_result(future): 
    print(future.result()) 

loop = asyncio.get_event_loop() 
future = asyncio.Future() 
future.add_done_callback(got_result) 
asyncio.async(slow_operation()) 
try: 
    loop.run_forever() 
finally: 
    loop.close() 
:

Task exception was never retrieved 
future: <Task finished coro=<slow_operation() done, defined at ./asynchio-test3.py:5> exception=InvalidStateError("FINISHED: <Future finished result='This is the future!'>",)> 

이 내가 미래에 관한 3 선을 제거하면 예상대로 실행 내 코드입니다

답변

2

slow_operator은 무기한으로 호출되며 같은 미래의 개체에 대해 여러 번 호출합니다 (set_result). 그것은 가능하지 않다.

>>> import asyncio 
>>> future = asyncio.Future() 
>>> future.set_result('result') 
>>> future.set_result('result') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "C:\Python35\lib\asyncio\futures.py", line 329, in set_result 
    raise InvalidStateError('{}: {!r}'.format(self._state, self)) 
asyncio.futures.InvalidStateError: FINISHED: <Future finished result='result'> 

slow_operator 전화에 대해 새로운 미래를 만듭니다. 예를 들어 :

@asyncio.coroutine 
def slow_operation(future): 
    yield from asyncio.sleep(1) 
    print ("This is the task!") 
    future.set_result('This is the future!') 
    asyncio.async(slow_operation(new_future())) 

def got_result(future): 
    print(future.result()) 

def new_future(): 
    future = asyncio.Future() 
    future.add_done_callback(got_result) 
    return future 

loop = asyncio.get_event_loop() 
asyncio.async(slow_operation(new_future())) 
try: 
    loop.run_forever() 
finally: 
    loop.close() 

BTW, 당신은 3.5 파이썬을 사용하는 경우 새로운 구문 (async, await)를 사용할 수 있습니다 :

async def slow_operation(future): 
    await asyncio.sleep(1) 
    print ("This is the task!") 
    future.set_result('This is the future!') 
    asyncio.ensure_future(slow_operation(new_future())) 
+0

아주 멋지다. 고맙습니다. 하지만 이제 어쨌든 왜 선물이 필요한지 묻는 단계에 있습니다. 쿠로틴에서 정규 함수를 호출 할 수 있습니까? 아니면 future가 무엇입니까? set_result? 필요한거야? – dpetican

+0

@dpetican, 죄송합니다, 나는 대답 할 수 없습니다. 별도의 질문을 올리시겠습니까? – falsetru

+0

짧은 대답은 비동기가 필요한지 여부에 달려 있습니다. – dirn

1

다음이 완전한 프로그램입니다 대답 @falsetru 그 자신의 got_result 함수로 각각 3 개의 비동기 코 루틴이 있습니다. 나는 왜 새로운 구문을 사용하지 않는지에 대해 v3.4를 사용하고 있습니다. 흥미로운 부작용으로 출력물은 코 루틴의 단일 스레드 특성을 명확하게 보여줍니다. 그 사람을위한 템플릿으로 유용 희망 :

import asyncio 

@asyncio.coroutine 
def task1(future): 
    yield from asyncio.sleep(1) 
    print ("This is operation#1") 
    future.set_result('This is the result of operation #1!') 
    asyncio.async(task1(new_future(got_result1))) 

def got_result1(future): 
    print(future.result()) 

@asyncio.coroutine 
def task2(future): 
    yield from asyncio.sleep(1) 
    print ("This is operation#2") 
    future.set_result('This is the result of operation #2!') 
    asyncio.async(task2(new_future(got_result2))) 

def got_result2(future): 
    print(future.result()) 

@asyncio.coroutine 
def task3(future): 
    yield from asyncio.sleep(1) 
    print ("This is operation#3") 
    future.set_result('This is the result of operation #3!') 
    asyncio.async(task3(new_future(got_result3))) 

def got_result3(future): 
    print(future.result()) 

def new_future(callback): 
    future = asyncio.Future() 
    future.add_done_callback(callback) 
    return future 

tasks = [task1(new_future(got_result1)), 
     task2(new_future(got_result2)), 
     task3(new_future(got_result3))] 

loop = asyncio.get_event_loop() 
for task in tasks: 
    asyncio.async(task) 

try: 
    loop.run_forever() 
finally: 
    loop.close() 
관련 문제