摘要:具有以下基本同步原語子進(jìn)程提供了通過創(chuàng)建和管理子進(jìn)程的。雖然隊(duì)列不是線程安全的,但它們被設(shè)計(jì)為專門用于代碼。表示異步操作的最終結(jié)果。
Python的asyncio是使用 async/await 語法編寫并發(fā)代碼的標(biāo)準(zhǔn)庫。通過上一節(jié)的講解,我們了解了它不斷變化的發(fā)展歷史。到了Python最新穩(wěn)定版 3.7 這個(gè)版本,asyncio又做了比較大的調(diào)整,把這個(gè)庫的API分為了 高層級API和低層級API,并引入asyncio.run()這樣的高級方法,讓編寫異步程序更加簡潔。
本節(jié)希望提綱挈領(lǐng)地介紹最新 3.7 版的asnycio,先從全局認(rèn)識Python這個(gè)異步IO庫。
asyncio的高層級API主要提高如下幾個(gè)方面:
并發(fā)地運(yùn)行Python協(xié)程并完全控制其執(zhí)行過程;
執(zhí)行網(wǎng)絡(luò)IO和IPC;
控制子進(jìn)程;
通過隊(duì)列實(shí)現(xiàn)分布式任務(wù);
同步并發(fā)代碼。
asyncio的低層級API用以支持開發(fā)異步庫和框架:
創(chuàng)建和管理事件循環(huán)(event loop),提供異步的API用于網(wǎng)絡(luò),運(yùn)行子進(jìn)程,處理操作系統(tǒng)信號等;
通過transports實(shí)現(xiàn)高效率協(xié)議;
通過async/await 語法橋架基于回調(diào)的庫和代碼。
asyncio高級API高層級API讓我們更方便的編寫基于asyncio的應(yīng)用程序。這些API包括:
(1)協(xié)程和任務(wù)協(xié)程通過 async/await 語法進(jìn)行聲明,是編寫異步應(yīng)用的推薦方式。歷史的?@asyncio.coroutine?和?yield from?已經(jīng)被棄用,并計(jì)劃在Python 3.10中移除。協(xié)程可以通過?asyncio.run(coro, *, debug=False)?函數(shù)運(yùn)行,該函數(shù)負(fù)責(zé)管理事件循環(huán)并完結(jié)異步生成器。它應(yīng)該被用作asyncio程序的主入口點(diǎn),相當(dāng)于main函數(shù),應(yīng)該只被調(diào)用一次。
任務(wù)被用于并發(fā)調(diào)度協(xié)程,可用于網(wǎng)絡(luò)爬蟲的并發(fā)。使用?asyncio.create_task()?就可以把一個(gè)協(xié)程打包為一個(gè)任務(wù),該協(xié)程會自動(dòng)安排為很快運(yùn)行。
協(xié)程,任務(wù)和Future都是可等待對象。其中,F(xiàn)uture是低層級的可等待對象,表示一個(gè)異步操作的最終結(jié)果。
(2)流流是用于網(wǎng)絡(luò)連接的高層級的使用 async/await的原語。流允許在不使用回調(diào)或低層級協(xié)議和傳輸?shù)那闆r下發(fā)送和接收數(shù)據(jù)。異步讀寫TCP有客戶端函數(shù)?asyncio.open_connection()?和 服務(wù)端函數(shù)?asyncio.start_server()?。它還支持 Unix Sockets:?asyncio.open_unix_connection()?和?asyncio.start_unix_server()。
(3)同步原語asyncio同步原語的設(shè)計(jì)類似于threading模塊的原語,有兩個(gè)重要的注意事項(xiàng):
asyncio原語不是線程安全的,因此它們不應(yīng)該用于OS線程同步(而是用threading)
這些同步原語的方法不接受超時(shí)參數(shù); 使用asyncio.wait_for()函數(shù)執(zhí)行超時(shí)操作。
asyncio具有以下基本同步原語:
Lock
Event
Condition
Semaphore
BoundedSemaphore
(4)子進(jìn)程asyncio提供了通過 async/await 創(chuàng)建和管理子進(jìn)程的API。不同于Python標(biāo)準(zhǔn)庫的subprocess,asyncio的子進(jìn)程函數(shù)都是異步的,并且提供了多種工具來處理這些函數(shù),這就很容易并行執(zhí)行和監(jiān)視多個(gè)子進(jìn)程。創(chuàng)建子進(jìn)程的方法主要有兩個(gè):
coroutine asyncio.create_subprocess_exec()
coroutine asyncio.create_subprocess_shell()
asyncio 隊(duì)列的設(shè)計(jì)類似于標(biāo)準(zhǔn)模塊queue的類。雖然asyncio隊(duì)列不是線程安全的,但它們被設(shè)計(jì)為專門用于 async/await 代碼。需要注意的是,asyncio隊(duì)列的方法沒有超時(shí)參數(shù),使用?asyncio.wait_for()函數(shù)進(jìn)行超時(shí)的隊(duì)列操作。
因?yàn)楹蜆?biāo)注模塊queue的類設(shè)計(jì)相似,使用起來跟queue無太多差異,只需要在對應(yīng)的函數(shù)前面加 await 即可。asyncio 隊(duì)列提供了三種不同的隊(duì)列:
class asyncio.Queue 先進(jìn)先出隊(duì)列
class asyncio.PriorityQueue 優(yōu)先隊(duì)列
class asyncio.LifoQueue 后進(jìn)先出隊(duì)列
(6)異常asyncio提供了幾種異常,它們是:
TimeoutError,
CancelledError,
InvalidStateError,
SendfileNotAvailableError
IncompleteReadError
LimitOverrunError
asyncio低級API低層級API為編寫基于asyncio的庫和框架提供支持,有意編寫異步庫和框架的大牛們需要熟悉這些低層級API。主要包括:
(1)事件循環(huán)事件循環(huán)是每個(gè)asyncio應(yīng)用程序的核心。 事件循環(huán)運(yùn)行異步任務(wù)和回調(diào),執(zhí)行網(wǎng)絡(luò)IO操作以及運(yùn)行子進(jìn)程。
應(yīng)用程序開發(fā)人員通常應(yīng)該使用高級asyncio函數(shù),例如asyncio.run(),并且很少需要引用循環(huán)對象或調(diào)用其方法。
Python 3.7 新增了?asyncio.get_running_loop()函數(shù)。
(2)FuturesFuture對象用于將基于低層級回調(diào)的代碼與高層級的 async/await 代碼進(jìn)行橋接。
Future表示異步操作的最終結(jié)果。 不是線程安全的。
Future是一個(gè)可等待對象。 協(xié)程可以等待Future對象,直到它們有結(jié)果或異常集,或者直到它們被取消。
通常,F(xiàn)utures用于啟用基于低層級回調(diào)的代碼(例如,在使用asyncio傳輸實(shí)現(xiàn)的協(xié)議中)以與高層級 async/await 代碼進(jìn)行互操作。
Transport 和 Protocol由低層級事件循環(huán)使用,比如函數(shù)loop.create_connection()。它們使用基于回調(diào)的編程風(fēng)格,并支持網(wǎng)絡(luò)或IPC協(xié)議(如HTTP)的高性能實(shí)現(xiàn)。
在最高級別,傳輸涉及字節(jié)的傳輸方式,而協(xié)議確定要傳輸哪些字節(jié)(在某種程度上何時(shí)傳輸)。
換種方式說就是:傳輸是套接字(或類似的I/O端點(diǎn))的抽象,而協(xié)議是從傳輸?shù)慕嵌葋砜吹膽?yīng)用程序的抽象。
另一種觀點(diǎn)是傳輸和協(xié)議接口共同定義了一個(gè)使用網(wǎng)絡(luò)I/O和進(jìn)程間I/O的抽象接口。
傳輸和協(xié)議對象之間始終存在1:1的關(guān)系:協(xié)議調(diào)用傳輸方法來發(fā)送數(shù)據(jù),而傳輸調(diào)用協(xié)議方法來傳遞已接收的數(shù)據(jù)。
大多數(shù)面向連接的事件循環(huán)方法(例如loop.create_connection())通常接受protocol_factory參數(shù),該參數(shù)用于為接受的連接創(chuàng)建Protocol對象,由Transport對象表示。 這些方法通常返回(傳輸,協(xié)議)元組。
(4)策略(Policy)事件循環(huán)策略是一個(gè)全局的按進(jìn)程劃分的對象,用于控制事件循環(huán)的管理。 每個(gè)事件循環(huán)都有一個(gè)默認(rèn)策略,可以使用策略API對其進(jìn)行更改和自定義。
策略定義了上下文的概念,并根據(jù)上下文管理多帶帶的事件循環(huán)。 默認(rèn)策略將上下文定義為當(dāng)前線程。
通過使用自定義事件循環(huán)策略,可以自定義get_event_loop(),set_event_loop()和new_event_loop()函數(shù)的行為。
(5)平臺支持asyncio模塊設(shè)計(jì)為可移植的,但由于平臺的底層架構(gòu)和功能,某些平臺存在細(xì)微的差異和限制。在Windows平臺,有些是不支持的,比如?loop.create_unix_connection()?and?loop.create_unix_server()。而Linux和比較新的macOS全部支持。
總結(jié)Python 3.7 通過對asyncio分組使得它的架構(gòu)更加清晰,普通寫異步IO的應(yīng)用程序只需熟悉高層級API,需要寫異步IO的庫和框架時(shí)才需要理解低層級的API。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/43852.html
摘要:并發(fā)的方式有多種,多線程,多進(jìn)程,異步等。多線程和多進(jìn)程之間的場景切換和通訊代價(jià)很高,不適合密集型的場景關(guān)于多線程和多進(jìn)程的特點(diǎn)已經(jīng)超出本文討論的范疇,有興趣的同學(xué)可以自行搜索深入理解。 編程中,我們經(jīng)常會遇到并發(fā)這個(gè)概念,目的是讓軟件能充分利用硬件資源,提高性能。并發(fā)的方式有多種,多線程,多進(jìn)程,異步IO等。多線程和多進(jìn)程更多應(yīng)用于CPU密集型的場景,比如科學(xué)計(jì)算的時(shí)間都耗費(fèi)在CPU...
摘要:創(chuàng)建第一個(gè)協(xié)程推薦使用語法來聲明協(xié)程,來編寫異步應(yīng)用程序。協(xié)程兩個(gè)緊密相關(guān)的概念是協(xié)程函數(shù)通過定義的函數(shù)協(xié)程對象調(diào)用協(xié)程函數(shù)返回的對象。它是一個(gè)低層級的可等待對象,表示一個(gè)異步操作的最終結(jié)果。 我們講以Python 3.7 上的asyncio為例講解如何使用Python的異步IO。 showImg(https://segmentfault.com/img/remote/14600000...
摘要:快速開始在安裝之前在支持異步的過程中,都經(jīng)歷了哪些比較重大的更新。踏出第一步我們將正式使用來構(gòu)建一個(gè)項(xiàng)目,讓我們踏出第一步,利用來編寫一個(gè)返回字符串的服務(wù)程序。本次示例的源代碼全部在上,見。 快速開始 在安裝Sanic之前,讓我們一起來看看Python在支持異步的過程中,都經(jīng)歷了哪些比較重大的更新。 首先是Python3.4版本引入了asyncio,這讓Python有了支持異步IO的標(biāo)...
摘要:的異步代碼分析是的一個(gè)框架,基于,所以叫。不可避免的,可讀性會比較差。想找教程的話,請移步官方教程,寫得還是挺不錯(cuò)的。建議不要直接使用,而只把它當(dāng)成的一個(gè)樣例。 Python 的異步 IO:Aiohttp Client 代碼分析 Aiohttp 是 Python 的一個(gè) HTTP 框架,基于 asyncio,所以叫 Aiohttp。 我主要是看源碼,想理解它的設(shè)計(jì),所以附上了類圖與時(shí)序...
閱讀 2474·2021-09-27 13:36
閱讀 2170·2019-08-29 18:47
閱讀 2136·2019-08-29 15:21
閱讀 1401·2019-08-29 11:14
閱讀 1987·2019-08-28 18:29
閱讀 1631·2019-08-28 18:04
閱讀 578·2019-08-26 13:58
閱讀 3214·2019-08-26 12:12