【python】異步IO

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後:性能

  1. 首先調用c.send(None)啓動生成器;

  2. 而後,一旦生產了東西,經過c.send(n)切換到consumer執行;

  3. consumer經過yield拿到消息,處理,又經過yield把結果傳回;

  4. produce拿到consumer處理的結果,繼續生產下一條消息;

  5. produce決定不生產了,經過c.close()關閉consumer,整個過程結束。

整個流程無鎖,由一個線程執行,produceconsumer協做完成任務,因此稱爲「協程」,而非線程的搶佔式多任務

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:

asyncawait是針對coroutine的新語法,要使用新的語法,只須要作兩步簡單的替換:

  1. @asyncio.coroutine替換爲async
  2. 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()

運行結果

相關文章
相關標籤/搜索