我剛接觸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.↩
'同時不future.done()'或是,應該是'同時不stop_future.done()'? – Evert
@Evert。是的,thnx。 – voscausa