No1:html
協程看上去也是子程序,但執行過程當中,在子程序內部可中斷,而後轉而執行別的子程序,在適當的時候再返回來接着執行。web
優點:多線程
1.最大的優點就是協程極高的執行效率。由於子程序切換不是線程切換,而是由程序自身控制,所以,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優點就越明顯。併發
2.不須要多線程的鎖機制,由於只有一個線程,也不存在同時寫變量衝突,在協程中控制共享資源不加鎖,只須要判斷狀態就行了,因此執行效率比多線程高不少。app
No2:異步
由於協程是一個線程執行,那怎麼利用多核CPU呢?最簡單的方法是多進程+協程,既充分利用多核,又充分發揮協程的高效率,可得到極高的性能。async
Python對協程的支持是經過generator實現的。函數
def consumer(): r = '' while True: n = yield r if not n: return print('[CONSUMER] Consuming %s...' % n) r = '200 OK' def produce(c): c.send(None) n = 0 while n < 5: n = n + 1 print('[PRODUCER] Producing %s...' % n) r = c.send(n) print('[PRODUCER] Consumer return: %s' % r) c.close() c = consumer() produce(c)
運行結果oop
consumer
函數是一個generator
,把一個consumer
傳入produce
後:性能
首先調用c.send(None)
啓動生成器;
而後,一旦生產了東西,經過c.send(n)
切換到consumer
執行;
consumer
經過yield
拿到消息,處理,又經過yield
把結果傳回;
produce
拿到consumer
處理的結果,繼續生產下一條消息;
produce
決定不生產了,經過c.close()
關閉consumer
,整個過程結束。
整個流程無鎖,由一個線程執行,produce
和consumer
協做完成任務,因此稱爲「協程」,而非線程的搶佔式多任務
No3:
【asyncio】
import asyncio async def hello(): print("Hello world!") r=await asyncio.sleep(1) print("Hello again!") loop=asyncio.get_event_loop() loop.run_until_complete(hello()) loop.close()
運行結果
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()
運行結果
import asyncio @asyncio.coroutine def wget(host): print('wget %s...' % host) connect=asyncio.open_connection(host,80) reader,writer=yield from connect header='GET / HTTP/1.0\r\nHost:%s\r\n\r\n' % host writer.write(header.encode('utf-8')) yield from writer.drain() while True: line = yield from reader.readline() if line == b'\r\n': break print('%s header > %s' % (host,line.decode('utf-8').rstrip())) writer.close() loop=asyncio.get_event_loop() tasks=[wget(host) for host in ['www.sina.com.cn','www.sohu.com','www.163.com']] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
運行結果
No4:
異步操做須要在coroutine
中經過yield from
完成;
多個coroutine
能夠封裝成一組Task而後併發執行。
No5:
async
和await
是針對coroutine的新語法,要使用新的語法,只須要作兩步簡單的替換:
@asyncio.coroutine
替換爲async
;yield from
替換爲await
。No6:
【aiohttp】
import asyncio from aiohttp import web async def index(request): await asyncio.sleep(0.5) return web.Response(body=b'<h1>Index</h1>', content_type='text/html') async def hello(request): await asyncio.sleep(0.5) text='<h1>hello,%s!</h1>' % request.match_info['name'] return web.Response(body=text.encode('utf-8'), content_type='text/html') async def init(loop): app=web.Application(loop=loop) app.router.add_route('GET','/',index) app.router.add_route('GET','/hello/{name}',hello) srv=await loop.create_server(app.make_handler(),'127.0.0.1',8000) print('Server started at http://127.0.0.1:8000...') return srv loop=asyncio.get_event_loop() loop.run_until_complete(init(loop)) loop.run_forever()
運行結果