1、初識asyncio協程

初識asyncio協程

1、基本概念

​ 要想了解學習協程相關知識要先對如下幾個概念先行了解:python

  • 阻塞程序員

    ​ 阻塞狀態是指程序未獲得某所需計算資源時的掛起狀態,簡單說就是程序在等待某個操做未執行完前沒法執行其餘操做。網絡

  • 非阻塞併發

    ​ 非阻塞狀態是指在等待某項操做執行完前能夠繼續運行其餘操做,也就是不會被阻塞。框架

  • 同步異步

    ​ 不一樣程序單元爲了完成某項任務,在執行過程當中以某種通訊方式保證協調一致,假若有一個售票窗口,你必須等前面的人買完票,輪到你才能買,簡言之同步意味着有序。async

  • 異步函數

    ​ 不一樣程序單元爲了完成某項任務,在執行過程當中無需進行通訊也能完成任務,例如爬蟲,只要抓取目標url便可,無需關心其它抓取目標,簡言之異步意味着無序。oop

  • 併發性能

    ​ 簡單說就是操做系統在處理多個任務時快速切換,例如你在看電視時來電話了,此時你選擇關閉電視,接完電話再打開看,這樣的過程就是併發;

  • 並行

    ​ 簡單說就是操做系統同時處理多個任務,例如你在看電視時來電話了,此時你選擇邊看電視邊接電話,這樣的過程就是並行。

  • 協程

    ​ 協程擁有本身的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其餘地方,在切回來的時候,恢復先前保存的寄存器上下文和棧。所以協程能保留上一次調用時的狀態,即全部局部狀態的一個特定組合,每次過程重入時,就至關於進入上一次調用的狀態。

2、asyncio 異步I/O

asyncio是用來編寫併發代碼的庫,被用做多個提供高性能異步框架的基礎,每每是構建I/O密集型和高層級結構化網絡代碼的最佳選擇。

​ 在瞭解asyncio的使用方法前,首先有必要先介紹一下,這幾個貫穿始終的概念:

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

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

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

  • future對象:表明未來執行或沒有執行的任務的結果,與task沒有本質上的區別。

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

3、定義一個協程

​ 幹看概念總歸是難以理解並記住的,下面動手來實現一個協程

from collection.abc import Coroutine

async def a(name):
    print('hello',name)

if __name__ == '__main__':
    test = a('world')   # 輸出 hello world
    print(isinstance(test,Coroutine))  # 輸出 True

經過以上的實例咱們就完成了一個最簡單的協程,能夠發現其與普通函數不一樣的僅僅是在函數名前加了async

4、協程的工做流程

一個完整的協程工做流程以下:

  • 定義/建立一個協程對象

  • 將協程轉爲task任務
  • 定義事件循環容器
  • 將task任務放到事件循環容器觸發

參照下面示例能夠完整了解這個流程:

import asyncio

async def a(name):  # 定義一個協程
    print('hello',name)

if __name__ == "__main__":
    coroutine = a('world')  # 第一步,定義一個協程對象
    task = asyncio.ensure_future(coroutine)  # 第二步,將協程轉換成task任務
    loop = asyncio.get_event_loop()  # 第三步,定義一個事件循環容器
    loop.run_until_complete(task)  # 第四步,將task任務放到事件循環容器

5、阻塞和await

​ 在程序運行過程當中遇到耗時的操做時會掛起該協程,轉而執行別的協程,當掛起的協程運行完畢時再從別的協程切換回去,不等當前這個協程運沒運行完畢。舉個例子:假若有協程A和協程B,當協程A遇到阻塞耗時的操做時便轉向運行協程B,當協程A的耗時操做結束再從協程B切換回去,無論協程B有沒有運行完畢。

​ 由前面asyncio的概念能夠知道,使用await能夠掛起一個協程。

import asyncio

async def a(name):
    await asyncio.sleep(3)  # 模擬耗時的操做,不用time.sleep是由於time模塊不支持異步
    print('hello',name)
    
if __name__ == "__main__":
    coroutine = a('world')
    loop = asyncio.get_event_loop()
    loop.run_until_complete(coroutine)

補充說明await後面的對象必須的格式:

  • 原生協程(coroutine)對象
  • 一個由types.coroutine()修飾的生成器
  • 一個包含_await方法的對象返回的一個迭代器
    簡言之就是協程,任務,Future三種

總結:至此咱們已經初步瞭解了什麼是異步,什麼是asyncio,以及協程的工做流程,並進行了實踐。

相關文章
相關標籤/搜索