Python學習筆記__20.2章 asyncio

# 這是學習廖雪峯老師python教程的學習筆記html

一、概覽python

asyncioPython 3.4版本引入的標準庫,直接內置了對異步IO的支持web

asyncio的編程模型就是一個消息循環。咱們從asyncio模塊中直接獲取一個EventLoop的引用,而後把須要執行的協程扔到EventLoop中執行,就實現了異步IO。編程

1.一、asyncioio的關鍵字網絡

  • event_loop      事件循環:程序開啓一個無限循環,把一些函數註冊到事件循環上,當知足事件發生的時候,調用相應的協程函數併發

  • coroutine      協程:協程對象,指一個使用async關鍵字定義的函數,它的調用不會當即執行函數,而是會返回一個協程對象。協程對象須要註冊到事件循環,由事件循環調用。app

  • task      任務:一個協程對象就是一個原生能夠掛起的函數,任務則是對協程進一步封裝,其中包含了任務的各類狀態異步

  • future: 表明未來執行或沒有執行的任務的結果。它和task上沒有本質上的區別socket

  • async/await      關鍵字:python3.5用於定義協程的關鍵字,async定義一個協程,await用於掛起阻塞的異步調用接口。async

 

 

 

二、實例

2.一、用asyncio實現Hello world

import asyncio

 

@asyncio.coroutine # generator標記爲coroutine類型

def hello():

    print("Hello world!")

    r = yield from asyncio.sleep(1) # 異步調用asyncio.sleep(1)

    print("Hello again!")

 

 

loop = asyncio.get_event_loop() # 建立消息事件,開啓了事件循環

loop.run_until_complete(hello())  # 將協程對象註冊到事件循環,由事件循環調用

loop.close() # 關閉事件

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

由於loop裏只有一個事件【hello()】,因此會暫停1秒,打印「hello again

2.二、用Task封裝兩個coroutine

import threading

import asyncio

 

@asyncio.coroutine # generator標記爲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)) #asyncio.wait()等待子進程終止

loop.close() # 關閉消息事件

 

# 執行過程

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)>)

# 解析

這裏的loop裏有兩個hello事件,下面簡稱h1和h2。

  1. 首先h1被執行,打印了"Hello      world",異步執行了asyncio.sleep(1),須要暫停1

  2. loop不會等待,將h1掛起,直接執行h2,又打印了"Hello      world",而後又碰到asyncio.sleep(1),須要暫停1

  3. 1秒後,再次執行h1h2,由於CPU處理速度很快,因此雖然h2h1晚暫停,可是幾乎感受不到

 

2.3、用asyncio的異步網絡鏈接來獲取sinasohu163的網站首頁

import asyncio

 

@asyncio.coroutine # generator標記爲coroutine類型

def wget(host):

    print('wget %s...' % host)

    connect = asyncio.open_connection(host, 80) #建立異步鏈接

    reader, writer = yield from connect #異步調用connect,返回readerwriter兩個實例,這是固定的兩個實例

    header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host  # 設置header

    writer.write(header.encode('utf-8'))

    yield from writer.drain() # 將設置的header寫入connect

    while True:

        line = yield from reader.readline() #讀取返回的HTTP

        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()

 

# 執行結果

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併發完成

3、小結

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

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

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

 

4、擴展文檔

python中重要的模塊--asyncio (http://www.javashuo.com/article/p-okfxrbuu-c.html)

python yield yield from (https://blog.csdn.net/chenbin520/article/details/78111399?locationNum=7&fps=1)

相關文章
相關標籤/搜索