Python中使用asyncio 封裝文件讀寫
前言
和網(wǎng)絡 IO 一樣,文件讀寫同樣是一個費事的操作。
默認情況下,Python 使用的是系統(tǒng)的阻塞讀寫。這意味著在 asyncio 中如果調用了
f = file('xx') f.read()
會阻塞事件循環(huán)。
本篇簡述如何用 asyncio.Future 對象來封裝文件的異步讀寫。
代碼在 GitHub。目前僅支持 Linux。
阻塞和非阻塞
首先需要將文件的讀寫改為非阻塞的形式。在非阻塞情況下,每次調用 read 都會立即返回,如果返回值為空,則意味著文件操作還未完成,反之則是讀取的文件內(nèi)容。
阻塞和非阻塞的切換與操作系統(tǒng)有關,所以本篇暫時只寫了 Linux 版本。如果有過 Unix 系統(tǒng)編程經(jīng)驗,會發(fā)現(xiàn) Python 的操作是類似的。
flag = fcntl.fcntl(self.fd, fcntl.F_GETFL) if fcntl.fcntl(self.fd, fcntl.F_SETFL, flag | os.O_NONBLOCK) != 0: raise OSError()
Future 對象
Future 對象類似 Javascript 中的 Promise 對象。它是一個占位符,其值會在將來被計算出來。我們可以使用
result = await future
在 future 得到值之后返回。而使用
future.set_result(xxx)
就可以設置 future 的值,也意味著 future 可以被返回了。await 操作符會自動調用 future.result() 來得到值。
loop.call_soon
通過 loop.call_soon 方法可以將一個函數(shù)插入到事件循環(huán)中。
至此,我們的異步文件讀寫思路也就出來了。通過 loop.call_soon 調用非阻塞讀寫文件的函數(shù)。若一次文件讀寫沒有完成,則計算剩余所學讀寫的字節(jié)數(shù),并再次插入事件循環(huán)直至讀寫完畢。
可以發(fā)現(xiàn)其就是把傳統(tǒng) Unix 編程里,非阻塞文件讀寫的 while 循環(huán)換成了 asyncio 的事件循環(huán)。
下面是這一過程的示意代碼。
def read_step(self, future, n, total): res = self.fd.read(n) if res is None: self.loop.call_soon(self.read_step, future, n, total) return if not res: # EOF future.set_result(bytes(self.rbuffer)) return self.rbuffer.extend(res) self.loop.call_soon(self.read_step, future, self.BLOCK_SIZE, total) def read(self, n=-1): future = asyncio.Future(loop=self.loop) self.rbuffer.clear() self.loop.call_soon(self.read_step, future, min(self.BLOCK_SIZE, n), n) return future
相關文章
python處理文本文件實現(xiàn)生成指定格式文件的方法
這篇文章主要介紹了python處理文本文件實現(xiàn)生成指定格式文件的方法,有一定的實用價值,需要的朋友可以參考下2014-07-07python去除字符串中的空格、特殊字符和指定字符的三種方法
本文主要介紹了python去除字符串中的空格、特殊字符和指定字符的三種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-02-02Python數(shù)據(jù)分析之Matplotlib的常用操作總結
Matplotlib是Python的繪圖庫,它可與NumPy一起使用,提供了一種有效的MatLab開源替代方案,下面這篇文章主要給大家介紹了關于Python數(shù)據(jù)分析之Matplotlib常用操作的相關資料,需要的朋友可以參考下2022-01-01Python?ttkbootstrap?制作賬戶注冊信息界面的案例代碼
ttkbootstrap 是一個基于 tkinter 的界面美化庫,使用這個工具可以開發(fā)出類似前端 bootstrap 風格的 tkinter 桌面程序。本文重點給大家介紹Python?ttkbootstrap?制作賬戶注冊信息界面的案例代碼,感興趣的朋友一起看看吧2022-02-02