成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

Python協(xié)程asyncio模塊的演變及高級(jí)用法

瀏覽:4日期:2022-06-19 14:56:16
目錄Python協(xié)程及asyncio基礎(chǔ)知識(shí)定義協(xié)程函數(shù)及執(zhí)行方法的演變創(chuàng)建協(xié)程任務(wù)的演變獲取協(xié)程任務(wù)執(zhí)行結(jié)果通過asyncio.gather獲取協(xié)程任務(wù)執(zhí)行結(jié)果asyncio高級(jí)使用方法給任務(wù)添加回調(diào)函數(shù)設(shè)置任務(wù)超時(shí)自省Python協(xié)程及asyncio基礎(chǔ)知識(shí)

協(xié)程(coroutine)也叫微線程,是實(shí)現(xiàn)多任務(wù)的另一種方式,是比線程更小的執(zhí)行單元,一般運(yùn)行在單進(jìn)程和單線程上。因?yàn)樗詭PU的上下文,它可以通過簡單的事件循環(huán)切換任務(wù),比進(jìn)程和線程的切換效率更高,這是因?yàn)檫M(jìn)程和線程的切換由操作系統(tǒng)進(jìn)行。

Python實(shí)現(xiàn)協(xié)程的主要借助于兩個(gè)庫:asyncio和gevent。由于asyncio已經(jīng)成為python的標(biāo)準(zhǔn)庫了無需pip安裝即可使用,這意味著asyncio作為Python原生的協(xié)程實(shí)現(xiàn)方式會(huì)更加流行。本文僅會(huì)介紹asyncio模塊。如果大家對(duì)gevent也有需求,請(qǐng)留言,我會(huì)單獨(dú)寫篇文章介紹這個(gè)庫的使用。

asyncio 是從Python3.4引入的標(biāo)準(zhǔn)庫,直接內(nèi)置了對(duì)協(xié)程異步IO的支持。asyncio 的編程模型本質(zhì)是一個(gè)消息循環(huán),我們一般先定義一個(gè)協(xié)程函數(shù)(或任務(wù)), 從 asyncio 模塊中獲取事件循環(huán)loop,然后把需要執(zhí)行的協(xié)程任務(wù)(或任務(wù)列表)扔到 loop中執(zhí)行,就實(shí)現(xiàn)了異步IO。

定義協(xié)程函數(shù)及執(zhí)行方法的演變

在最早的Python 3.4中,協(xié)程函數(shù)是通過@asyncio.coroutine 和 yeild from 實(shí)現(xiàn)的, 如下所示。

import asyncio @asyncio.coroutine def func1(i): print('協(xié)程函數(shù){}馬上開始執(zhí)行。'.format(i)) yield from asyncio.sleep(2) print('協(xié)程函數(shù){}執(zhí)行完畢!'.format(i)) if __name__ == ’__main__’: # 獲取事件循環(huán) loop = asyncio.get_event_loop() # 執(zhí)行協(xié)程任務(wù) loop.run_until_complete(func1(1)) # 關(guān)閉事件循環(huán) loop.close()

這里我們定義了一個(gè)func1的協(xié)程函數(shù),我們可以使用asyncio.iscoroutinefunction來驗(yàn)證。定義好協(xié)程函數(shù)后,我們首先獲取事件循環(huán)loop,使用它的run_until_complete方法執(zhí)行協(xié)程任務(wù),然后關(guān)閉loop。

print(asyncio.iscoroutinefunction(func1(1))) # True

Python 3.5以后引入了async/await 語法定義協(xié)程函數(shù),代碼如下所示。每個(gè)協(xié)程函數(shù)都以async聲明,以區(qū)別于普通函數(shù),對(duì)于耗時(shí)的代碼或函數(shù)我們使用await聲明,表示碰到等待時(shí)掛起,以切換到其它任務(wù)。

import asyncio # 這是一個(gè)協(xié)程函數(shù) async def func1(i): print('協(xié)程函數(shù){}馬上開始執(zhí)行。'.format(i)) await asyncio.sleep(2) print('協(xié)程函數(shù){}執(zhí)行完畢!'.format(i)) if __name__ == ’__main__’: # 獲取事件循環(huán) loop = asyncio.get_event_loop() # 執(zhí)行協(xié)程任務(wù) loop.run_until_complete(func1(1)) # 關(guān)閉事件循環(huán) loop.close()

Python 3.7之前執(zhí)行協(xié)程任務(wù)都是分三步進(jìn)行的,代碼有點(diǎn)冗余。Python 3.7提供了一個(gè)更簡便的asyncio.run方法,上面代碼可以簡化為:

import asyncio async def func1(i): print(f'協(xié)程函數(shù){i}馬上開始執(zhí)行。') await asyncio.sleep(2) print(f'協(xié)程函數(shù){i}執(zhí)行完畢!') if __name__ == ’__main__’: asyncio.run(func1(1))

注:Python自3.6版本起可以使用f-string來對(duì)字符串進(jìn)行格式化了,相當(dāng)于format函數(shù)的簡化版。

創(chuàng)建協(xié)程任務(wù)的演變

前面的演示案例中,我們只執(zhí)行了單個(gè)協(xié)程任務(wù)(函數(shù))。實(shí)際應(yīng)用中,我們先由協(xié)程函數(shù)創(chuàng)建協(xié)程任務(wù),然后把它們加入?yún)f(xié)程任務(wù)列表,最后一起交由事件循環(huán)執(zhí)行。

根據(jù)協(xié)程函數(shù)創(chuàng)建協(xié)程任務(wù)有多種方法,其中最新的是Python 3.7版本提供的asyncio.create_task方法,如下所示:

# 方法1:使用ensure_future方法。future代表一個(gè)對(duì)象,未執(zhí)行的任務(wù)。 task1 = asyncio.ensure_future(func1(1)) task2 = asyncio.ensure_future(func1(2)) # 方法2:使用loop.create_task方法 task1 = loop.create_task(func1(1)) task2 = loop.create_task(func1(2)) # 方法3:使用Python 3.7提供的asyncio.create_task方法 task1 = asyncio.create_task(func1(1)) task2 = asyncio.create_task(func1(2))

創(chuàng)建多個(gè)協(xié)程任務(wù)列表后,我們還要使用asyncio.wait方法收集協(xié)程任務(wù),并交由事件循環(huán)處理執(zhí)行。

import asyncio async def func1(i): print(f'協(xié)程函數(shù){i}馬上開始執(zhí)行。') await asyncio.sleep(2) print(f'協(xié)程函數(shù){i}執(zhí)行完畢!') async def main(): tasks = [] # 創(chuàng)建包含4個(gè)協(xié)程任務(wù)的列表 for i in range(1, 5): tasks.append(asyncio.create_task(func1(i))) await asyncio.wait(tasks) if __name__ == ’__main__’: asyncio.run(main())

執(zhí)行效果如下所示,你會(huì)發(fā)現(xiàn)4個(gè)協(xié)程任務(wù)并不是按順序執(zhí)行的。

Python協(xié)程asyncio模塊的演變及高級(jí)用法

對(duì)于收集多個(gè)協(xié)程任務(wù),Python還提供了新的asyncio.gather方法,它的作用asyncio.wait方法類似,但更強(qiáng)大。如果列表中傳入的不是create_task方法創(chuàng)建的協(xié)程任務(wù),它會(huì)自動(dòng)將函數(shù)封裝成協(xié)程任務(wù),如下所示:

import asyncio async def func1(i): print(f'協(xié)程函數(shù){i}馬上開始執(zhí)行。') await asyncio.sleep(2) print(f'協(xié)程函數(shù){i}執(zhí)行完畢!') async def main(): tasks = [] for i in range(1, 5): # 這里未由協(xié)程函數(shù)創(chuàng)建協(xié)程任務(wù) tasks.append(func1(i)) # 注意這里*號(hào)。gather自動(dòng)將函數(shù)列表封裝成了協(xié)程任務(wù)。 await asyncio.gather(*tasks) if __name__ == ’__main__’: asyncio.run(main())獲取協(xié)程任務(wù)執(zhí)行結(jié)果

是的,gather方法有將函數(shù)封裝成協(xié)程任務(wù)的能力,但這還并不是兩者最主要的區(qū)別作用。兩者更大的區(qū)別在協(xié)程任務(wù)執(zhí)行完畢后對(duì)于返回結(jié)果的處理上。通常獲取任務(wù)執(zhí)行結(jié)果通常對(duì)于一個(gè)程序至關(guān)重要,因此我們有必要花更多時(shí)間詳細(xì)了解這兩個(gè)方法的使用。

asyncio.wait 會(huì)返回兩個(gè)值:done 和 pending,done 為已完成的協(xié)程任務(wù)列表,pending 為超時(shí)未完成的協(xié)程任務(wù)類別,需通過task.result()方法可以獲取每個(gè)協(xié)程任務(wù)返回的結(jié)果;而asyncio.gather 返回的是所有已完成協(xié)程任務(wù)的 result,不需要再進(jìn)行調(diào)用或其他操作,就可以得到全部結(jié)果。

我們來看兩個(gè)示例。現(xiàn)在修改我們的協(xié)程函數(shù),通過return給它增加一個(gè)返回值。

通過asyncio.wait獲取協(xié)程任務(wù)執(zhí)行結(jié)果

import asyncio async def func1(i): print(f'協(xié)程函數(shù){i}馬上開始執(zhí)行。') await asyncio.sleep(2) return i async def main(): tasks = [] for i in range(1, 5): tasks.append(asyncio.create_task(func1(i))) # 獲取任務(wù)執(zhí)行結(jié)果。 done, pending = await asyncio.wait(tasks) for task in done: print(f'執(zhí)行結(jié)果: {task.result()}') if __name__ == ’__main__’: asyncio.run(main())

執(zhí)行結(jié)果如下所示。你可以看到協(xié)程任務(wù)執(zhí)行結(jié)果并不是按任務(wù)添加的順序返回的。

Python協(xié)程asyncio模塊的演變及高級(jí)用法

通過asyncio.gather獲取協(xié)程任務(wù)執(zhí)行結(jié)果

繼續(xù)修改我們的代碼:

#-*- coding:utf-8 -*- import asyncio async def func1(i): print(f'協(xié)程函數(shù){i}馬上開始執(zhí)行。') await asyncio.sleep(2) return i async def main(): tasks = [] for i in range(1, 5): tasks.append(func1(i)) results = await asyncio.gather(*tasks) for result in results: print(f'執(zhí)行結(jié)果: {result}') if __name__ == ’__main__’: asyncio.run(main())

執(zhí)行結(jié)果如下所示。協(xié)程任務(wù)執(zhí)行結(jié)果與任務(wù)添加順序完全一致。

Python協(xié)程asyncio模塊的演變及高級(jí)用法

現(xiàn)在你知道gather和wait方法的真正區(qū)別了嗎?

gather具有把普通協(xié)程函數(shù)包裝成協(xié)程任務(wù)的能力,wait沒有。wait只能接收包裝后的協(xié)程任務(wù)列表做參數(shù)。 兩者返回值不一樣,wait返回的是已完成和未完成任務(wù)的列表,而gather直接返回協(xié)程任務(wù)執(zhí)行結(jié)果。 gather返回的任務(wù)執(zhí)行結(jié)果是有序的,wait方法獲取的結(jié)果是無序的。asyncio高級(jí)使用方法給任務(wù)添加回調(diào)函數(shù)

我們還可以給每個(gè)協(xié)程任務(wù)通過add_done_callback的方法給單個(gè)協(xié)程任務(wù)添加回調(diào)函數(shù),如下所示:

#-*- coding:utf-8 -*- import asyncio async def func1(i): print(f'協(xié)程函數(shù){i}馬上開始執(zhí)行。') await asyncio.sleep(2) return i # 回調(diào)函數(shù) def callback(future): print(f'執(zhí)行結(jié)果:{future.result()}') async def main(): tasks = [] for i in range(1, 5): task = asyncio.create_task(func1(i)) # 注意這里,增加回調(diào)函數(shù) task.add_done_callback(callback) tasks.append(task) await asyncio.wait(tasks) if __name__ == ’__main__’: asyncio.run(main())設(shè)置任務(wù)超時(shí)

很多協(xié)程任務(wù)都是很耗時(shí)的,當(dāng)你使用wait方法收集協(xié)程任務(wù)時(shí),可通過timeout選項(xiàng)設(shè)置任務(wù)切換前單個(gè)任務(wù)最大等待時(shí)間長度,如下所示:

# 獲取任務(wù)執(zhí)行結(jié)果,如下所示: done,pending = await asyncio.wait(tasks, timeout=10)自省 asyncio.current_task: 返回當(dāng)前運(yùn)行的Task實(shí)例,如果沒有正在運(yùn)行的任務(wù)則返回 None。如果 loop 為 None 則會(huì)使用 get_running_loop()獲取當(dāng)前事件循環(huán)。 asyncio.all_tasks: 返回事件循環(huán)所運(yùn)行的未完成的Task對(duì)象的集合。

以上就是Python協(xié)程asyncio模塊的演變及高級(jí)用法的詳細(xì)內(nèi)容,更多關(guān)于Python協(xié)程asyncio模塊的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
久久综合九色综合欧美98| 欧美女孩性生活视频| 久久婷婷一区| 中文字幕国产一区二区| 成人av资源下载| 91麻豆精品国产自产在线 | 欧美一区二区三区不卡| 日韩成人一级片| 免费在线一区二区| 一级精品视频在线观看宜春院| 欧美日韩国产免费观看| 久久久久88色偷偷免费| www.激情成人| 日韩精品资源二区在线| 国产在线乱码一区二区三区| 欧美色爱综合网| 免费成人在线网站| 色天天综合色天天久久| 日韩精品一级中文字幕精品视频免费观看| 国产亚洲综合精品| 一二三区精品福利视频| 一本综合久久| 一级中文字幕一区二区| 国产伦精品一区二区三区视频孕妇| 亚洲欧美日韩一区二区三区在线观看| 亚洲午夜极品| 国产精品国产三级国产aⅴ入口| 91免费视频网| 国产婷婷色一区二区三区在线| 波多野结衣一区二区三区| 欧美tickling挠脚心丨vk| 成年人午夜久久久| 久久综合久久综合亚洲| 成人国产精品免费观看动漫| 精品乱码亚洲一区二区不卡| 不卡av在线网| 精品国一区二区三区| 你懂的国产精品| 欧美极品美女视频| 国内成+人亚洲| 亚洲欧美另类久久久精品| 一本久道综合久久精品| 亚洲一区二区五区| 色婷婷国产精品| 久久国产免费看| 欧美日韩一区二区在线观看| 国产一区二区三区日韩| 精品欧美黑人一区二区三区| 欧美福利在线| 一区二区欧美国产| 色乱码一区二区三区88| 韩国视频一区二区| 欧美成人国产一区二区| 国产精品mm| 亚洲综合一区二区精品导航| 色哟哟精品一区| 国产乱码字幕精品高清av| xfplay精品久久| 激情另类综合| 亚洲国产一区二区在线播放| 欧美又粗又大又爽| 丰满白嫩尤物一区二区| 国产欧美一区二区三区在线老狼| 韩国自拍一区| 樱花影视一区二区| 欧美色综合影院| 99久久婷婷国产综合精品 | 久久精品一二三区| 麻豆精品国产91久久久久久| 日韩三级在线观看| 激情欧美亚洲| 天堂在线亚洲视频| 欧美高清激情brazzers| 色综合久久中文综合久久97| 亚洲另类色综合网站| 91久久奴性调教| 成人av电影免费在线播放| 亚洲欧美国产77777| 欧美三级乱人伦电影| 女女同性精品视频| 亚洲18色成人| 欧美一卡二卡三卡| 极品尤物久久久av免费看| 日韩电影免费一区| 欧美变态tickling挠脚心| 99精品国产99久久久久久福利| 久久av中文字幕片| www国产亚洲精品久久麻豆| 亚洲欧洲在线一区| 精品午夜久久福利影院| 国产偷v国产偷v亚洲高清| 亚洲欧美大片| 成人在线综合网站| 一区二区在线观看免费| 欧美日韩国产一区二区三区地区| 欧美另类亚洲| 丝袜美腿亚洲一区| 2023国产精品自拍| 美女网站久久| 成人avav影音| 日韩精品三区四区| 久久久久久久精| 噜噜噜噜噜久久久久久91| 91色九色蝌蚪| 精品夜夜嗨av一区二区三区| 中文字幕欧美激情一区| 欧美午夜宅男影院| 欧美三日本三级少妇三99| 蜜桃视频一区二区三区在线观看| 久久一区二区视频| 久久一综合视频| 女女同性精品视频| 国精品**一区二区三区在线蜜桃| 中文字幕一区二区三区在线播放 | 韩日精品视频| 国产一区不卡视频| 夜夜嗨av一区二区三区四季av | 亚洲国产中文字幕| 欧美激情在线观看视频免费| 欧美日本韩国一区二区三区视频| 亚洲精品在线视频观看| 成人动漫一区二区三区| 日韩电影免费在线看| 国产精品激情偷乱一区二区∴| 欧美酷刑日本凌虐凌虐| 亚洲自拍另类| 欧美日韩国产一区精品一区| 国产成人精品网址| 日本成人超碰在线观看| 亚洲精品欧美二区三区中文字幕| xvideos.蜜桃一区二区| 欧美日韩高清一区二区不卡| 亚洲一区成人| 欧美性久久久| 成人免费毛片嘿嘿连载视频| 日韩高清欧美激情| 亚洲免费色视频| 欧美激情一区不卡| 欧美一区二区三区在线观看| 久久亚洲精品欧美| 99视频+国产日韩欧美| 91麻豆福利精品推荐| 国产成人免费视频网站高清观看视频| 亚洲国产日韩综合久久精品| 国产精品视频观看| 精品国产凹凸成av人导航| 欧美日韩国产一二三| 久久性色av| 99视频一区| 欧美片第1页综合| caoporn国产精品| 国产成人综合在线播放| 九色综合狠狠综合久久| 午夜久久久久久| 亚洲激情图片一区| 中文字幕亚洲综合久久菠萝蜜| 久久网站最新地址| 91精品一区二区三区在线观看| 色94色欧美sute亚洲13| 国产欧美激情| 日韩亚洲国产精品| 伊人激情综合| 欧美精品aa| 91无套直看片红桃| 成人黄色777网| 国产成人aaa| 国产sm精品调教视频网站| 麻豆成人久久精品二区三区红| 亚洲国产精品精华液网站| 亚洲人吸女人奶水| 国产精品国产自产拍在线| 国产精品伦理在线| 国产精品伦一区| 国产精品高清亚洲| 国产精品国产三级国产有无不卡 | www.久久精品| aaa亚洲精品| av电影在线观看不卡| av中文字幕不卡| 99精品1区2区| 91在线视频免费91| 不卡高清视频专区| 91一区二区在线观看| 91麻豆精品秘密| 欧美日韩免费观看一区| 欧美日韩在线观看一区二区三区| 午夜精品剧场| 黄色av日韩| 国产欧美一区二区色老头 | 日韩欧美国产综合一区 | 在线电影一区二区三区| 88在线观看91蜜桃国自产| 欧美视频你懂的| 7777精品伊人久久久大香线蕉完整版 | 91亚洲精品久久久蜜桃| 国产欧美综合色| 欧美日韩国内| 中文字幕巨乱亚洲| 99久久777色| 亚洲国产高清一区二区三区|