async /await相關知識理解

asyncio提供的@asyncio.coroutine能夠把一個generator標記爲coroutine類型,而後在coroutine內部用yield from調用另外一個coroutine實現異步操做。html

爲了簡化並更好地標識異步IO,從Python 3.5開始引入了新的語法asyncawait,能夠讓coroutine的代碼更簡潔易讀。網絡

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

  

  1. @asyncio.coroutine替換爲async
  2. yield from替換爲await


實例1:

@asyncio.coroutine把一個generator標記爲coroutine類型,而後,咱們就把這個coroutine扔到EventLoop中執行。異步

hello()會首先打印出Hello world!,而後,yield from語法能夠讓咱們方便地調用另外一個generator。因爲asyncio.sleep()也是一個coroutine,因此線程不會等待asyncio.sleep(),而是直接中斷並執行下一個消息循環。當asyncio.sleep()返回時,線程就能夠從yield from拿到返回值(此處是None),而後接着執行下一行語句。socket

asyncio.sleep(1)當作是一個耗時1秒的IO操做,在此期間,主線程並未等待,而是去執行EventLoop中其餘能夠執行的coroutine了,所以能夠實現併發執行。async

咱們用Task封裝兩個coroutine試試:oop

 

asyncio的異步網絡鏈接來獲取sina、sohu和163的網站首頁:網站

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()))
    # Ignore the body, close the socket
    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()

result:spa

wget www.sohu.com...
wget www.sina.com.cn...
wget www.163.com...
(等待一段時間)
(打印出sohu的header)
www.sohu.com header > HTTP/1.1 200 OK
www.sohu.com header > Content-Type: text/html
...
(打印出sina的header)
www.sina.com.cn header > HTTP/1.1 200 OK
www.sina.com.cn header > Date: Wed, 20 May 2015 04:56:33 GMT
...
(打印出163的header)
www.163.com header > HTTP/1.0 302 Moved Temporarily
www.163.com header > Server: Cdn Cache Server V2.0
...

可見3個鏈接由一個線程經過coroutine併發完成。線程

 

小結

asyncio提供了完善的異步IO支持;

異步操做須要在coroutine中經過yield from完成;

多個coroutine能夠封裝成一組Task而後併發執行。

 

 

實例2:async

import asyncio
import time

start = time.time()


def tic():
    return 'at %1.1f seconds' % (time.time() - start)


async def gr1():
    # Busy waits for a second, but we don't want to stick around...
    print('gr1 started work: {}'.format(tic()))
    # 暫停兩秒,但不阻塞時間循環,下同
    await asyncio.sleep(2)
    print('gr1 ended work: {}'.format(tic()))


async def gr2():
    # Busy waits for a second, but we don't want to stick around...
    print('gr2 started work: {}'.format(tic()))
    await asyncio.sleep(2)
    print('gr2 Ended work: {}'.format(tic()))


async def gr3():
    print("Let's do some stuff while the coroutines are blocked, {}".format(tic()))
    await asyncio.sleep(1)
    print("Done!")

# 事件循環
ioloop = asyncio.get_event_loop()

# tasks中也能夠使用asyncio.ensure_future(gr1())..
tasks = [
    ioloop.create_task(gr1()),
    ioloop.create_task(gr2()),
    ioloop.create_task(gr3())
]
ioloop.run_until_complete(asyncio.wait(tasks))
ioloop.close()


output:
    gr1 started work: at 0.0 seconds
    gr2 started work: at 0.0 seconds
    Let's do some stuff while the coroutines are blocked, at 0.0 seconds
    Done!
    gr2 Ended work: at 2.0 seconds
    gr1 ended work: at 2.0 seconds

相關文章
相關標籤/搜索