亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

python異步IO編程(一)

系統(tǒng) 1818 0

python異步IO編程(一)

基礎(chǔ)概念

協(xié)程:python ?generator與coroutine

異步IO (async IO):一種由多種語言實現(xiàn)的與語言無關(guān)的范例(或模型)。

asyncio:Python 3.4版本引入的標準庫,直接內(nèi)置了對異步IO的支持。

?

異步IO

線程,多線程

多線程善于處理I/O密集型任務(wù)。
多進程擅長處理計算密集型(CPU-bound)任務(wù):強密集循環(huán)和數(shù)學(xué)計算都屬于此類。
并發(fā)是并行的一種特殊類型(或者說子類),多線程是并發(fā)的表現(xiàn)形式,多進程是并行的表現(xiàn)形式。
Python通過它的包 multiprocessing,threading 和 concurrent.futures 已經(jīng)對這兩種形式都提供了長期的支持。

?

異步IO

異步IO是一種單進程、單線程的設(shè)計:它使用協(xié)同多任務(wù)處理機制,是以協(xié)程為核心的一種編程模型。
異步IO并不是新發(fā)明的概念,它已經(jīng)存在或正在被構(gòu)建到其他語言及運行時環(huán)境中,如 Go,C# 和 Scala 等。
異步IO模型異步IO采用消息循環(huán)的模式,在消息循環(huán)中,主線程不斷地重復(fù)“讀取消息-處理消息”這一過程:

            loop = get_event_loop() //
            
              實例消息隊列

            
            
              while
            
            
               True:
event 
            
            = loop.get_event() //
            
              從隊列中讀取消息
process_event(event)    
            
            //處理消息消息模型其實早在應(yīng)用在桌面應(yīng)用程序中了。一個GUI程序的主線程就負責不停地讀取消息并處理消息。所有的鍵盤、鼠標等消息都被發(fā)送到GUI程序的消息隊列中,然后由GUI程序的主線程處理。
          

由于GUI線程處理鍵盤、鼠標等消息的速度非常快,所以用戶感覺不到延遲。某些時候,GUI線程在一個消息處理的過程中遇到問題導(dǎo)致一次消息處理時間過長,此時,用戶會感覺到整個GUI程序停止響應(yīng)了,敲鍵盤、點鼠標都沒有反應(yīng)。
這種情況說明在消息模型中,處理一個消息必須非常迅速,否則,主線程將無法及時處理消息隊列中的其他消息,導(dǎo)致程序看上去停止響應(yīng)。
消息模型是如何解決同步IO必須等待IO操作這一問題的呢?當遇到IO操作時,代碼只負責發(fā)出IO請求,不等待IO結(jié)果,然后直接結(jié)束本輪消息處理,進入下一輪消息處理過程。當IO操作完成后,將收到一條“IO完成”的消息,處理該消息時就可以直接獲取IO操作結(jié)果。
在“發(fā)出IO請求”到收到“IO完成”的這段時間里,同步IO模型下,主線程只能掛起,但異步IO模型下,主線程并沒有休息,而是在消息循環(huán)中繼續(xù)處理其他消息。這樣,在異步IO模型下,一個線程就可以同時處理多個IO請求,并且沒有切換線程的操作。對于大多數(shù)IO密集型的應(yīng)用程序,使用異步IO將大大提升系統(tǒng)的多任務(wù)處理能力。

?

?

asyncio

async與asyncio.coroutine

在 python3.5 中,創(chuàng)建一個協(xié)程僅僅只需使用 async 關(guān)鍵字,而python3.4使用 @asyncio.coroutine 裝飾器。都引入了原生協(xié)程或者說異步生成器。下面的任一代碼,都可以作為協(xié)程工作,形式上也是等同的:

            
              import
            
            
               asyncio

async 
            
            
              def
            
             ping_server(ip): 
            
              #
            
            
               3.5
            
            
              pass
            
            
              

@asyncio.coroutine

            
            
              def
            
             load_file(path): 
            
              #
            
            
               3.4
            
            
              pass
            
          

? python異步IO編程(一)_第1張圖片

?

yield from與await

3.1 中協(xié)程操作只是簡單的生成器調(diào)用,常見的我們還需要在生成器或者說協(xié)程之間相互調(diào)用,用到y(tǒng)ield from。yield from 用于一個generator調(diào)用另一個generator,主要是為了generator之間的調(diào)用。
yield from 表達式的使用方式如下:

            
              import
            
            
               asyncio
@asyncio.coroutine

            
            
              def
            
            
               get_jason(client, url):
file_content 
            
            = 
            
              yield
            
            
              from
            
             load_file(
            
              '
            
            
              /Usrs/scott/data.txt
            
            
              '
            
            )
          

?

協(xié)程的一個關(guān)鍵特性是它們可以被鏈接到一起。(記住,一個協(xié)程是可等待的,所以另一個協(xié)程可以使用? await ?來等待它。)await 將控制器傳遞給時間循環(huán)。(掛起當前運行的協(xié)程與yield from類似),使用方式如下:

            async 
            
              def
            
            
               ping_local(ip):
  
            
            
              return
            
             await ping_server(
            
              '
            
            
              192.168.1.1
            
            
              '
            
            )
          

Python3.5 對這兩種調(diào)用協(xié)程的方法都提供了支持,但是推薦 async/await 作為首選。


Python執(zhí)行的時候, g() 函數(shù)范圍內(nèi)如果遇到表達式 await f(),就是 await 在告訴事件循環(huán)“掛起 g() 函數(shù),直到 f() 返回結(jié)果,在此期間,可以運行其他函數(shù)。”

            async 
            
              def
            
            
               g():

            
            
              #
            
            
              暫停,直到 f()結(jié)束再回到g()
            
            
  r =
            
               await f()
  
            
            
              return
            
             r
          

當你使用 await f() 時,要求 f() 是一個可等待的對象。但這并沒有什么用。現(xiàn)在,只需要知道可等待對象要么是(1)其他的協(xié)程,要么就是(2)定義了 .await() 函數(shù)且返回迭代器的對象。如果你正在編寫程序,絕大多數(shù)情況只需要關(guān)注案例#1。

使用規(guī)則

1. 使用 await 與 return 的組合創(chuàng)建協(xié)程函數(shù)。想要調(diào)用一個協(xié)程函數(shù),必須使用 await 等待返回結(jié)果。
2. 在 async def 代碼塊中使用 yield 的情況并不多見(只有Python的近期版本才可用)。當你使用 async for 進行迭代的時候,會創(chuàng)建一個異步生成器。暫時先忘掉異步生成器,將目光放在使用 await 與 return 的組合創(chuàng)建協(xié)程函數(shù)的語法上。
3. 在任何使用 async def 定義的地方都不可以使用 yield from,這會引發(fā)異常 SyntaxError。
4. 一如在 def 定義的函數(shù)之外使用 yield 會引發(fā)異常 SyntaxError,在 async def 定義的協(xié)程之外使用 await 也會引發(fā)異常 SyntaxError。你只能在協(xié)程內(nèi)部使用 await。

? python異步IO編程(一)_第2張圖片

?

Event Loop

asyncio的編程模型就是一個消息循環(huán)。我們從asyncio模塊中直接獲取一個EventLoop的引用,然后把需要執(zhí)行的協(xié)程扔到EventLoop中執(zhí)行,就實現(xiàn)了異步IO。

用asyncio實現(xiàn)Hello world代碼如下:

            
              import
            
            
               asyncio

@asyncio.coroutine

            
            
              def
            
            
               hello():
  
            
            
              print
            
            (
            
              "
            
            
              Hello world!
            
            
              "
            
            
              )

            
            
              #
            
            
               異步調(diào)用asyncio.sleep(1):
            
            
  r = 
            
              yield
            
            
              from
            
             asyncio.sleep(1
            
              )
  
            
            
              print
            
            (
            
              "
            
            
              Hello again!
            
            
              "
            
            
              )


            
            
              #
            
            
               獲取EventLoop:
            
            
loop =
            
               asyncio.get_event_loop()

            
            
              #
            
            
               執(zhí)行coroutine
            
            
              loop.run_until_complete(hello())
loop.close()
            
          

@asyncio.coroutine把一個generator標記為coroutine類型,然后,我們就把這個coroutine扔到EventLoop中執(zhí)行。
hello()會首先打印出Hello world!,然后,yield from語法可以讓我們方便地調(diào)用另一個generator。由于asyncio.sleep()也是一個coroutine,所以線程不會等待asyncio.sleep(),而是直接中斷并執(zhí)行下一個消息循環(huán)。當asyncio.sleep()返回時,線程就可以從yield from拿到返回值(此處是None),然后接著執(zhí)行下一行語句。
把asyncio.sleep(1)看成是一個耗時1秒的IO操作,在此期間,主線程并未等待,而是去執(zhí)行EventLoop中其他可以執(zhí)行的coroutine了,因此可以實現(xiàn)并發(fā)執(zhí)行。

async/await版本:

            
              import
            
            
               asyncio

async 
            
            
              def
            
            
               hello():

            
            
              print
            
            (
            
              "
            
            
              Hello World
            
            
              "
            
            
              )
r 
            
            = await asyncio.sleep(1
            
              )

            
            
              print
            
            (
            
              "
            
            
              Again
            
            
              "
            
            
              )

loop 
            
            =
            
               asyncio.get_event_loop()
loop.run_until_complete(hello())
loop.close()
            
          

我們用Task封裝兩個coroutine試試:

            
              import
            
            
               threading

            
            
              import
            
            
               asyncio

@asyncio.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))
loop.close()
            
          

觀察執(zhí)行過程:
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)>)

由打印的當前線程名稱可以看出,兩個coroutine是由同一個線程并發(fā)執(zhí)行的。
如果把asyncio.sleep()換成真正的IO操作,則多個coroutine就可以由一個線程并發(fā)執(zhí)行。

?

?

參考:

https://mp.weixin.qq.com/s/fJaXmfHfYEk6XL2y8NmKmQ

https://www.jianshu.com/p/2dfaacdd0a90

?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 99热久久这里只有精品 | 亚洲精品第一综合99久久 | 久久国产精品自在自线 | 91在线欧美 | 成人在线午夜 | 2021久久精品永久免费 | 精品国产一区二区三区香蕉沈先生 | 精品在线播放视频 | 99re8免费视频精品全部 | 日日撸夜夜干 | 久草性视频 | 日本四虎影视 | 国内精品久久久久久久999下 | 老司机午夜在线视频 | 天天爽夜夜爽视频 | 国产精品一区久久 | 日韩字幕一中文在线综合 | 亚洲一区二区福利视频 | 97免费观看视频 | 亚洲小说春色综合另类网蜜桃 | 久久免费精品一区二区 | 夜夜操夜夜操 | 在线观看 亚洲 | 日日狠狠| 成人精品一区二区三区校园激情 | 欧美一级毛片片aa视频 | 久久久久久毛片免费播放 | 大尺度福利视频在线观看网址 | 国产综合色在线视频区色吧图片 | 国产一区二区在线看 | 中国美女一级a毛片录像在线 | 日本在线精品 | 黄色一级毛片 | 中文字幕久久综合伊人 | 国产高清一区二区三区免费视频 | 国产免费播放一区二区 | 亚洲欧美综合区自拍另类 | 国产日本欧美亚洲精品视 | 在线观看精品视频一区二区三区 | 天天干在线影院 | 免费看日韩欧美一级毛片 |