免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Python異步編程模塊asyncio學(xué)習(xí)

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

異步并發(fā)的概念

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

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

事件循環(huán)

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

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

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

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

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

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

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

Future

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

Task

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

異步方法

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

一個(gè)標(biāo)準(zhǔn)方法是這樣的:

而一個(gè)異步方法:

從外觀上看異步方法和標(biāo)準(zhǔn)方法沒什么區(qū)別只是前面多了個(gè)async。

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

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

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

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

句法錯(cuò)誤:

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

協(xié)程

啟動(dòng)一個(gè)協(xié)程

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

輸出

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

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

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

從協(xié)程中返回值

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

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

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

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

輸出

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

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

call_soon

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

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

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

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

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

輸出結(jié)果

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

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

call_later

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

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

配合上面的call_soon讓我們看一個(gè)小例子

輸出

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

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

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

call_at

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

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

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

輸出

因?yàn)閏all_later內(nèi)部實(shí)現(xiàn)就是通過call_at所以這里就不多說了。

Future

獲取Futrue里的結(jié)果

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

Pending

Running

Done

Cancelled

創(chuàng)建future的時(shí)候,task為pending,事件循環(huán)調(diào)用執(zhí)行的時(shí)候當(dāng)然就是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的實(shí)例all_done會(huì)保留提供給方法的結(jié)果,可以在后續(xù)使用。

Future對象使用await

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

Future回調(diào)

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

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

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

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

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

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

輸出

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

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

組合協(xié)程

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

等待多個(gè)協(xié)程

Task的使用

輸出

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

達(dá)到這個(gè)超時(shí)時(shí)間后,未完成的任務(wù)狀態(tài)變?yōu)閜ending,當(dāng)程序退出時(shí)還有任務(wù)沒有完成此時(shí)就會(huì)看到如下的錯(cuò)誤提示。

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

gather的使用

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

1.gather任務(wù)無法取消。

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

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

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

輸出

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

輸出

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

1.step1和step2是并行運(yùn)行的。

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

任務(wù)完成時(shí)進(jìn)行處理

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

輸出

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

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

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
理解 asyncio 來構(gòu)建高性能 Python 網(wǎng)絡(luò)程序
python協(xié)程系列(五)——asyncio的核心概念與基本架構(gòu)
Python黑魔法 --- 異步IO( asyncio) 協(xié)程
python asyncio 異步 I/O - 協(xié)程(Coroutine)與運(yùn)行
協(xié)程那些事兒(一)--你好,協(xié)程
解密 asyncio 的 Future 和 Task
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服