2015-11-07 52 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

相关问题