協程,又稱微線程,纖程。英文名Coroutine。一句話說明什麼是線程:協程是一種用戶態的輕量級線程。html
線程是系統級別的,它們是由操做系統調度;協程是程序級別的,由程序員根據須要本身調度。咱們把一個線程中的一個個函數叫作子程序,那麼子程序在執行過程當中能夠中斷去執行別的子程序;別的子程序也能夠中斷回來繼續執行以前的子程序,這就是協程。也就是說同一線程下的一段代碼<1>執行着執行着就能夠中斷,而後跳去執行另外一段代碼,當再次回來執行代碼塊<1>的時候,接着從以前中斷的地方開始執行。程序員
協程擁有本身的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其餘地方,在切回來的時候,恢復先前保存的寄存器上下文和棧。所以:協程能保留上一次調用時的狀態(即全部局部狀態的一個特定組合),每次過程重入時,就至關於進入上一次調用的狀態,換種說法:進入上一次離開時所處邏輯流的位置。編程
yield不但能夠返回一個值,它還能夠接收調用者發出的參數session
def consumer(): print('開始消費了') ret = '' while True: producter = yield ret if not producter: return print('消費了%s' % producter) ret = '200 ok' def produce(consu): # 啓動生成器,第一次必須用None <==> consumer.__next__() consu.send(None) n = 0 while n < 5: n += 1 print('生產了蘋果%d' % n) ret = consu.send('蘋果%d' % n) print('消費者返回:%s' % ret) consu.close() c = consumer() produce(c)
執行流程:
首先調用consu.send(None)啓動生成器;
而後,一旦生產了東西,經過consu.send(n)切換到consumer執行;
consumer經過yield拿到消息,處理,又經過yield把結果傳回;
produce拿到consumer處理的結果,繼續生產下一條消息;
produce決定不生產了,經過c.close()關閉consumer,整個過程結束。app
asyncio的編程模型就是一個消息循環框架
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()) # 獲取EventLoop: loop = asyncio.get_event_loop() tasks = [hello(), hello()] # 執行coroutine loop.run_until_complete(asyncio.wait(tasks)) loop.close()
import asyncio #async申明這是一個異步函數, await用於掛起自身,執行耗時操做 async def get(): await asyncio.sleep(1) return 100 async def hello(): print('開始了') # 模擬耗時操做 a = await get() print('結束了%s' % a) loop = asyncio.get_event_loop() tasks = [hello(), hello()] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
aiohttp是基於asyncio實現的HTTP框架異步
異步簡單爬蟲示例:async
import asyncio import aiohttp get_contents = [] async def html(url): headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'} async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers, timeout=1, verify_ssl=False) as r: body = await r.text() get_contents.append(body) loop = asyncio.get_event_loop() tasks = [html('http://www.baidu.com'), html('http://www.163.com')] loop.run_until_complete(asyncio.wait(tasks)) loop.close() print(len(get_contents))
輸出:
2函數