asyncio
是Python3.4版本引入的標準庫,直接內置了對異步IO的支持。編程
asyncio
的編程模型就是一個消息循環。咱們從asyncio
模塊中直接獲取一個EventLoop
的引用,而後把須要執行的協程扔到EventLoop
中執行,就實現了異步IO。
用asyncio
實現Hello world
代碼以下:併發
import asyncio @asyncio.coroutine def hello(): print("Hello world!") # 異步調用asyncio.sleep(1): r = yield from asyncio.sleep(1) print("Hello again!") # 獲取EventLoop: loop = asyncio.get_event_loop() # 執行coroutine loop.run_until_complete(hello()) loop.close()
@asyncio.corountine
把一個generator標記爲coroutine類型,而後,咱們就把這個協程扔到EventLoop
中執行。
hello()
會首先打印出Hellow world!
,而後,yield from
語法可讓咱們方便的調用另外一個generator
。因爲asyncio.sleep()
也是一個coroutine
,因此線程不會等待asyncio.sleep()
,而是直接中斷並執行下一個消息循環。當asyncio.sleep()
返回時,線程就能夠從yield from
拿到返回值(這裏是None),而後接着執行下一個語句。
把asyncio.sleep(1)
當作是一個耗時1秒的IO操做,在此期間,主線程並未等待,而失去執行EvenLoop
中其它能夠執行的coroutine
了,所以也能夠實現併發執行。異步
咱們用Task封裝兩個coroutine
試試:async
import threading import asyncio @asyncio.coroutine def hello(): print('Hello world! (%s)' % threading.currentThread()) yield from asyncio.sleep(1) print('Hello again! (%s)' % threading.currentThread()) loop = asyncio.get_event_loop() tasks = [hello(), hello()] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
結果:oop
Hello world! (<_MainThread(MainThread, started 140735195337472)>) Hello world! (<_MainThread(MainThread, started 140735195337472)>) (暫停約1秒) Hello again! (<_MainThread(MainThread, started 140735195337472)>) Hello again! (<_MainThread(MainThread, started 140735195337472)>)
由打印的線程名稱能夠看出,兩個coroutine
是由同一個線程併發執行的。線程
若是把asyncio.sleep()
換成真正的IO操做,則多個coroutine
就能夠由一個線程併發執行。code
- 一種方法是經過調用run_until_complete()
- 另一種就是調用run_forever()
run_until_complete內置的add_done_callback()。使用run_forever()的好處就是能夠自定義add_done_callback()方法,具體差別:
run_until_complete()協程
import asyncio async def sloww_operation(future): await asyncio.sleep(1) future.set_result('Future is done!') #獲得一個標準的事件循環 loop = asyncio.get_event_loop() future = asyncio.Future() asyncio.ensure_future(slow_operation(future)) print(loop.is_running()) loop.run_until_complete(future) print(future.result()) loop.close()
import asyncio async def slow_operation(future): await asyncio.sleep(1) future.set_result('Future is dong!') def got_result(future): print(future.result()) loop.stop() loop = asyncio.get_event_loop() future = asyncio.Future() asyncio.ensure_future(slow_operation(future)) future.add_done_callback(got_result) try: loop.run_forever() finally: loop.close()
import asyncio async def compute(x, y): print("Compute %s + %s ..." % (x, y)) await asyncio.sleep(1.0) return x + y async def print_sum(x, y): result = await compute(x, y) print("%s + %s = %s" % (x, y, result)) loop = asyncio.get_event_loop() loop.run_until_complete(print_sum(1, 2)) loop.close()
compute()
is chained to print_sum()
: print_sum()
coroutine waits until compute()
is completed before returning its result.事件