2015-11-07 50 views
2

我剛接觸Python 3.5 asyncio。爲什麼asyncio.wait不會等待FIRST_COMPLETED

在asyncio.wait我下面的代碼()不等待stop_future完成:

import asyncio 
import datetime 
from concurrent.futures import FIRST_COMPLETED 


def stop(): # callback after 12 seconds 

    print('stop', datetime.datetime.now()) 
    stop_future.set_result('Done!') 


async def display_dt(): 

    while not stop_future.done(): 
     print('dt-1', datetime.datetime.now()) 
     # sleep 5 seconds or stop_future done 
     asyncio.wait([await asyncio.sleep(5), stop_future], return_when=FIRST_COMPLETED) 
     print('dt-2', datetime.datetime.now()) 

    task = asyncio.Task.current_task() 
    task.cancel() 
    print(stop_future.result()) 


loop = asyncio.get_event_loop() 
stop_future = asyncio.Future() 
loop.call_later(12, stop) 
loop.run_until_complete(display_dt()) 
loop.close() 

結果:

dt-1 2015-11-08 00:49:37.324582 
dt-2 2015-11-08 00:49:42.325503 
dt-1 2015-11-08 00:49:42.325503 
dt-2 2015-11-08 00:49:47.326423 
dt-1 2015-11-08 00:49:47.326423 
stop 2015-11-08 00:49:49.327192 # async.wait stop_future not triggered 
dt-2 2015-11-08 00:49:52.327343 # while loop finishes here 
>>> Done! 

更新:

下面是更新函數display_dt的代碼。現在asyncio.wait工作正常。
但我不明白爲什麼上面的代碼與科羅不起作用??

@asyncio.coroutine # decorator necessary? It works fine without 
def display_dt(): 

    while not stop_future.done(): 
     print('dt-1', datetime.datetime.now()) 
     yield from asyncio.wait([asyncio.sleep(5), stop_future], return_when=FIRST_COMPLETED) 
     print('dt-2', datetime.datetime.now()) 

    task = asyncio.Task.current_task() 
    task.cancel() 
    print(stop_future.result()) 

結果:

dt-1 2015-11-08 01:19:06.289915 
dt-2 2015-11-08 01:19:11.290836 
dt-1 2015-11-08 01:19:11.290836 
dt-2 2015-11-08 01:19:16.291757 
dt-1 2015-11-08 01:19:16.291757 
stop 2015-11-08 01:19:18.292525 
dt-2 2015-11-08 01:19:18.292525 # async wait stop_future triggered 
Done! 

更新:必要 @ asyncio.coroutine#設計師嗎?

我找到了答案在this great chapter

的@ asyncio.coroutine裝飾並不神奇。事實上,如果它裝飾一個生成器函數並且PYTHONASYNCIODEBUG環境變量沒有被設置,那麼裝飾器幾乎不會做任何事情。它只是爲了框架的其他部分設置一個屬性_is_coroutine。它可以在all.↩

+0

'同時不future.done()'或是,應該是'同時不stop_future.done()'? – Evert

+0

@Evert。是的,thnx。 – voscausa

回答

5

與不飾@ asyncio.coroutine裸發電機使用ASYNCIO必須await.wait()協程,不await的協程,你傳球.wait()

async def display_dt(): 

    while not stop_future.done(): 
     print('dt-1', datetime.datetime.now()) 
     # sleep 5 seconds or stop_future done 
     await asyncio.wait([asyncio.sleep(5), stop_future], return_when=FIRST_COMPLETED) # <---- 
     print('dt-2', datetime.datetime.now()) 

    task = asyncio.Task.current_task() 
    task.cancel() 
    print(stop_future.result()) 

現在這相當於您的編輯,但使用本地協程(即async/await語法)。

更新表示結果:

dt-1 2015-11-08 13:14:21.910399 
dt-2 2015-11-08 13:14:26.911320 
dt-1 2015-11-08 13:14:26.911320 
dt-2 2015-11-08 13:14:31.912240 
dt-1 2015-11-08 13:14:31.912240 
stop 2015-11-08 13:14:33.913009 
dt-2 2015-11-08 13:14:33.913009 
Done! 
+0

好的和thnx。我已經更新了結果: – voscausa

相關問題