2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

Python異步編程模塊asyncio學習

 xiaoyimin 2019-03-23

asyncioPython3.4引入的一個標準庫,直接內(nèi)置了對異步IO的支持。asyncio模塊提供了使用協(xié)程構(gòu)建并發(fā)應用的工具。它使用一種單線程單進程的的方式實現(xiàn)并發(fā),應用的各個部分彼此合作, 可以顯示的切換任務,一般會在程序阻塞I/O操作的時候發(fā)生上下文切換如等待讀寫文件,或者請求網(wǎng)絡。同時asyncio也支持調(diào)度代碼在將來的某個特定事件運行,從而支持一個協(xié)程等待另一個協(xié)程完成,以處理系統(tǒng)信號和識別其他一些事件。

異步并發(fā)的概念

對于其他的并發(fā)模型大多數(shù)采取的都是線性的方式編寫。并且依賴于語言運行時系統(tǒng)或操作系統(tǒng)的底層線程或進程來適當?shù)馗淖兩舷挛?,而基于asyncio的應用要求應用代碼顯示的處理上下文切換。

asyncio提供的框架以事件循環(huán)(event loop)為中心,程序開啟一個無限的循環(huán),程序會把一些函數(shù)注冊到事件循環(huán)上。當滿足事件發(fā)生的時候,調(diào)用相應的協(xié)程函數(shù)。

事件循環(huán)

事件循環(huán)是一種處理多并發(fā)量的有效方式,在維基百科中它被描述為「一種等待程序分配事件或消息的編程架構(gòu)」,我們可以定義事件循環(huán)來簡化使用輪詢方法來監(jiān)控事件,通俗的說法就是「當A發(fā)生時,執(zhí)行B」。事件循環(huán)利用poller對象,使得程序員不用控制任務的添加、刪除和事件的控制。事件循環(huán)使用回調(diào)方法來知道事件的發(fā)生。它是asyncio提供的「中央處理設備」,支持如下操作:

注冊、執(zhí)行和取消延遲調(diào)用(超時)

創(chuàng)建可用于多種類型的通信的服務端和客戶端的Transports

啟動進程以及相關(guān)的和外部通信程序的Transports

將耗時函數(shù)調(diào)用委托給一個線程池

單線程(進程)的架構(gòu)也避免的多線程(進程)修改可變狀態(tài)的鎖的問題。

與事件循環(huán)交互的應用要顯示地注冊將運行的代碼,讓事件循環(huán)在資源可用時向應用代碼發(fā)出必要的調(diào)用。如:一個套接字再沒有更多的數(shù)據(jù)可以讀取,那么服務器會把控制全交給事件循環(huán)。

Future

future是一個數(shù)據(jù)結(jié)構(gòu),表示還未完成的工作結(jié)果。事件循環(huán)可以監(jiān)視Future對象是否完成。從而允許應用的一部分等待另一部分完成一些工作。

Task

task是Future的一個子類,它知道如何包裝和管理一個協(xié)程的執(zhí)行。任務所需的資源可用時,事件循環(huán)會調(diào)度任務允許,并生成一個結(jié)果,從而可以由其他協(xié)程消費。

異步方法

使用asyncio也就意味著你需要一直寫異步方法。

一個標準方法是這樣的:

而一個異步方法:

從外觀上看異步方法和標準方法沒什么區(qū)別只是前面多了個async。

“Async” 是“asynchronous”的簡寫,為了區(qū)別于異步函數(shù),我們稱標準函數(shù)為同步函數(shù),

從用戶角度異步函數(shù)和同步函數(shù)有以下區(qū)別:

要調(diào)用異步函數(shù),必須使用await關(guān)鍵字。 因此,不要寫regular_double(3),而是寫await async_double(3).

不能在同步函數(shù)里使用await,否則會出錯。

句法錯誤:

但是在異步函數(shù)中,await是被允許的:

協(xié)程

啟動一個協(xié)程

一般異步方法被稱之為協(xié)程(Coroutine)。asyncio事件循環(huán)可以通過多種不同的方法啟動一個協(xié)程。一般對于入口函數(shù),最簡答的方法就是使用run_until_complete,并將協(xié)程直接傳入這個方法。

輸出

這就是最簡單的一個協(xié)程的例子,下面讓我們了解一下上面的代碼.

第一步首先得到一個事件循環(huán)的應用也就是定義的對象loop??梢允褂媚J的事件循環(huán),也可以實例化一個特定的循環(huán)類(比如uvloop),這里使用了默認循環(huán)run_until_complete(coro)方法用這個協(xié)程啟動循環(huán),協(xié)程返回時這個方法將停止循環(huán)。

run_until_complete的參數(shù)是一個futrue對象。當傳入一個協(xié)程,其內(nèi)部會自動封裝成task,其中task是Future的子類。關(guān)于task和future后面會提到。

從協(xié)程中返回值

將上面的代碼,改寫成下面代碼

run_until_complete可以獲取協(xié)程的返回值,如果沒有給定返回值,則像函數(shù)一樣,默認返回None。

協(xié)程調(diào)用協(xié)程

一個協(xié)程可以啟動另一個協(xié)程,從而可以任務根據(jù)工作內(nèi)容,封裝到不同的協(xié)程中。我們可以在協(xié)程中使用await關(guān)鍵字,鏈式的調(diào)度協(xié)程,來形成一個協(xié)程任務流。向下面的例子一樣。

輸出

協(xié)程中調(diào)用普通函數(shù)

在協(xié)程中可以通過一些方法去調(diào)用普通的函數(shù)??梢允褂玫年P(guān)鍵字有call_soon,call_later,call_at。

call_soon

可以通過字面意思理解調(diào)用立即返回。

loop.call_soon(callback, *args, context=None)

在下一個迭代的時間循環(huán)中立刻調(diào)用回調(diào)函數(shù),大部分的回調(diào)函數(shù)支持位置參數(shù),而不支持”關(guān)鍵字參數(shù)”,如果是想要使用關(guān)鍵字參數(shù),則推薦使用functools.aprtial對方法進一步包裝.可選關(guān)鍵字context允許指定要運行的回調(diào)的自定義contextvars.Context。當沒有提供上下文時使用當前上下文。在Python 3.7中, asyncio

協(xié)程加入了對上下文的支持。使用上下文就可以在一些場景下隱式地傳遞變量,比如數(shù)據(jù)庫連接session等,而不需要在所有方法調(diào)用顯示地傳遞這些變量。

下面來看一下具體的使用例子。

輸出結(jié)果

通過輸出結(jié)果我們可以發(fā)現(xiàn)我們在協(xié)程中成功調(diào)用了一個普通函數(shù),順序的打印了1和2。

有時候我們不想立即調(diào)用一個函數(shù),此時我們就可以call_later延時去調(diào)用一個函數(shù)了。

call_later

loop.call_later(delay, callback, *args, context=None)

首先簡單的說一下它的含義,就是事件循環(huán)在delay多長時間之后才執(zhí)行callback函數(shù).

配合上面的call_soon讓我們看一個小例子

輸出

通過上面的輸出可以得到如下結(jié)果:

1.call_soon會在call_later之前執(zhí)行,和它的位置在哪無關(guān)

2.call_later的第一個參數(shù)越小,越先執(zhí)行。

call_at

loop.call_at(when, callback, *args, context=None)

call_at第一個參數(shù)的含義代表的是一個單調(diào)時間,它和我們平時說的系統(tǒng)時間有點差異,

這里的時間指的是事件循環(huán)內(nèi)部時間,可以通過loop.time獲取,然后可以在此基礎上進行操作。后面的參數(shù)和前面的兩個方法一樣。實際上call_later內(nèi)部就是調(diào)用的call_at。

輸出

因為call_later內(nèi)部實現(xiàn)就是通過call_at所以這里就不多說了。

Future

獲取Futrue里的結(jié)果

future表示還沒有完成的工作結(jié)果。事件循環(huán)可以通過監(jiān)視一個future對象的狀態(tài)來指示它已經(jīng)完成。future對象有幾個狀態(tài):

Pending

Running

Done

Cancelled

創(chuàng)建future的時候,task為pending,事件循環(huán)調(diào)用執(zhí)行的時候當然就是running,調(diào)用完畢自然就是done,如果需要停止事件循環(huán),就需要先把task取消,狀態(tài)為cancel。

輸出

可以通過輸出結(jié)果發(fā)現(xiàn),調(diào)用set_result之后future對象的狀態(tài)由pending變?yōu)閒inished,F(xiàn)uture的實例all_done會保留提供給方法的結(jié)果,可以在后續(xù)使用。

Future對象使用await

future和協(xié)程一樣可以使用await關(guān)鍵字獲取其結(jié)果。

Future回調(diào)

Future 在完成的時候可以執(zhí)行一些回調(diào)函數(shù),回調(diào)函數(shù)按注冊時的順序進行調(diào)用:

通過add_done_callback方法給funtrue任務添加回調(diào)函數(shù),當funture執(zhí)行完成的時候,就會調(diào)用回調(diào)函數(shù)。并通過參數(shù)future獲取協(xié)程執(zhí)行的結(jié)果。

到此為止,我們就學會了如何在協(xié)程中調(diào)用一個普通函數(shù)并獲取其結(jié)果。

并發(fā)的執(zhí)行任務

任務(Task)是與事件循環(huán)交互的主要途徑之一。任務可以包裝協(xié)程,可以跟蹤協(xié)程何時完成。任務是Future的子類,所以使用方法和future一樣。協(xié)程可以等待任務,每個任務都有一個結(jié)果,在它完成之后可以獲取這個結(jié)果。

因為協(xié)程是沒有狀態(tài)的,我們通過使用create_task方法可以將協(xié)程包裝成有狀態(tài)的任務。還可以在任務運行的過程中取消任務。

輸出

如果把上面的task.cancel注釋了我們可以得到正常情況下的結(jié)果,如下。

另外出了使用loop.create_task將協(xié)程包裝為任務外還可以使用asyncio.ensure_future(coroutine)建一個task。在python3.7中可以使用asyncio.create_task創(chuàng)建任務。

組合協(xié)程

一系列的協(xié)程可以通過await鏈式的調(diào)用,但是有的時候我們需要在一個協(xié)程里等待多個協(xié)程,比如我們在一個協(xié)程里等待1000個異步網(wǎng)絡請求,對于訪問次序有沒有要求的時候,就可以使用另外的關(guān)鍵字wait或gather來解決了。wait可以暫停一個協(xié)程,直到后臺操作完成。

等待多個協(xié)程

Task的使用

輸出

可以發(fā)現(xiàn)我們的結(jié)果并沒有按照數(shù)字的順序顯示,在內(nèi)部wait使用一個set保存它創(chuàng)建的Task實例。因為set是無序的所以這也就是我們的任務不是順序執(zhí)行的原因。wait的返回值是一個元組,包括兩個集合,分別表示已完成和未完成的任務。wait第二個參數(shù)為一個超時值

達到這個超時時間后,未完成的任務狀態(tài)變?yōu)閜ending,當程序退出時還有任務沒有完成此時就會看到如下的錯誤提示。

此時我們可以通過迭代調(diào)用cancel方法取消任務。也就是這段代碼

gather的使用

gather的作用和wait類似不同的是。

1.gather任務無法取消。

2.返回值是一個結(jié)果列表

3.可以按照傳入?yún)?shù)的順序,順序輸出。

我們將上面的代碼改為gather的方式

輸出

gather通常被用來階段性的一個操作,做完第一步才能做第二步,比如下面這樣

輸出

可以通過上面結(jié)果得到如下結(jié)論:

1.step1和step2是并行運行的。

2.gather會等待最耗時的那個完成之后才返回結(jié)果,耗時總時間取決于其中任務最長時間的那個。

任務完成時進行處理

as_complete是一個生成器,會管理指定的一個任務列表,并生成他們的結(jié)果。每個協(xié)程結(jié)束運行時一次生成一個結(jié)果。與wait一樣,as_complete不能保證順序,不過執(zhí)行其他動作之前沒有必要等待所以后臺操作完成。

輸出

可以發(fā)現(xiàn)結(jié)果逐個輸出。

到此為止第一部分就結(jié)束了,對于asyncio入門級學習來說這些內(nèi)容就夠了。如果想繼續(xù)跟進asyncio的內(nèi)容,敬請期待后面的內(nèi)容。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多