乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

       xiaoyimin 2019-03-23

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

      異步并發(fā)的概念

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

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

      事件循環(huán)

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

      注冊(cè)、執(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)的鎖的問(wèn)題。

      與事件循環(huán)交互的應(yīng)用要顯示地注冊(cè)將運(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對(duì)象是否完成。從而允許應(yīng)用的一部分等待另一部分完成一些工作。

      Task

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

      異步方法

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

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

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

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

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

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

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

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

      句法錯(cuò)誤:

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

      協(xié)程

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

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

      輸出

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

      第一步首先得到一個(gè)事件循環(huán)的應(yīng)用也就是定義的對(duì)象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對(duì)象。當(dāng)傳入一個(gè)協(xié)程,其內(nèi)部會(huì)自動(dòng)封裝成task,其中task是Future的子類。關(guān)于task和future后面會(huì)提到。

      從協(xié)程中返回值

      將上面的代碼,改寫(xiě)成下面代碼

      run_until_complete可以獲取協(xié)程的返回值,如果沒(méi)有給定返回值,則像函數(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é)程,來(lái)形成一個(gè)協(xié)程任務(wù)流。向下面的例子一樣。

      輸出

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

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

      call_soon

      可以通過(guò)字面意思理解調(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對(duì)方法進(jìn)一步包裝.可選關(guān)鍵字context允許指定要運(yùn)行的回調(diào)的自定義contextvars.Context。當(dāng)沒(méi)有提供上下文時(shí)使用當(dāng)前上下文。在Python 3.7中, asyncio

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

      下面來(lái)看一下具體的使用例子。

      輸出結(jié)果

      通過(guò)輸出結(jié)果我們可以發(fā)現(xiàn)我們?cè)趨f(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)

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

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

      輸出

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

      1.call_soon會(huì)在call_later之前執(zhí)行,和它的位置在哪無(wú)關(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í)說(shuō)的系統(tǒng)時(shí)間有點(diǎn)差異,

      這里的時(shí)間指的是事件循環(huán)內(nèi)部時(shí)間,可以通過(guò)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)就是通過(guò)call_at所以這里就不多說(shuō)了。

      Future

      獲取Futrue里的結(jié)果

      future表示還沒(méi)有完成的工作結(jié)果。事件循環(huán)可以通過(guò)監(jiān)視一個(gè)future對(duì)象的狀態(tài)來(lái)指示它已經(jīng)完成。future對(duì)象有幾個(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。

      輸出

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

      Future對(duì)象使用await

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

      Future回調(diào)

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

      通過(guò)add_done_callback方法給funtrue任務(wù)添加回調(diào)函數(shù),當(dāng)funture執(zhí)行完成的時(shí)候,就會(huì)調(diào)用回調(diào)函數(shù)。并通過(guò)參數(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é)程是沒(méi)有狀態(tài)的,我們通過(guò)使用create_task方法可以將協(xié)程包裝成有狀態(tài)的任務(wù)。還可以在任務(wù)運(yùn)行的過(guò)程中取消任務(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é)程可以通過(guò)await鏈?zhǔn)降恼{(diào)用,但是有的時(shí)候我們需要在一個(gè)協(xié)程里等待多個(gè)協(xié)程,比如我們?cè)谝粋€(gè)協(xié)程里等待1000個(gè)異步網(wǎng)絡(luò)請(qǐng)求,對(duì)于訪問(wèn)次序有沒(méi)有要求的時(shí)候,就可以使用另外的關(guān)鍵字wait或gather來(lái)解決了。wait可以暫停一個(gè)協(xié)程,直到后臺(tái)操作完成。

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

      Task的使用

      輸出

      可以發(fā)現(xiàn)我們的結(jié)果并沒(méi)有按照數(shù)字的順序顯示,在內(nèi)部wait使用一個(gè)set保存它創(chuàng)建的Task實(shí)例。因?yàn)閟et是無(wú)序的所以這也就是我們的任務(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ù)沒(méi)有完成此時(shí)就會(huì)看到如下的錯(cuò)誤提示。

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

      gather的使用

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

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

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

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

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

      輸出

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

      輸出

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

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

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

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

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

      輸出

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

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

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

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多