亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Python中使用asyncio 封裝文件讀寫

Original 2017-01-16 14:01:31 399
abstract:前言和網(wǎng)絡(luò) IO 一樣,文件讀寫同樣是一個(gè)費(fèi)事的操作。默認(rèn)情況下,Python 使用的是系統(tǒng)的阻塞讀寫。這意味著在 asyncio 中如果調(diào)用了f = file('xx') f.read()會(huì)阻塞事件循環(huán)。本篇簡(jiǎn)述如何用 asyncio.Future 對(duì)象來(lái)封裝文件的異步讀寫。代碼在 GitHub。目前僅支持 Linux。阻塞和非阻塞首先需要將文件的讀

前言

和網(wǎng)絡(luò) IO 一樣,文件讀寫同樣是一個(gè)費(fèi)事的操作。

默認(rèn)情況下,Python 使用的是系統(tǒng)的阻塞讀寫。這意味著在 asyncio 中如果調(diào)用了

f = file('xx')
f.read()

會(huì)阻塞事件循環(huán)。

本篇簡(jiǎn)述如何用 asyncio.Future 對(duì)象來(lái)封裝文件的異步讀寫。

代碼在 GitHub。目前僅支持 Linux。

阻塞和非阻塞

首先需要將文件的讀寫改為非阻塞的形式。在非阻塞情況下,每次調(diào)用 read 都會(huì)立即返回,如果返回值為空,則意味著文件操作還未完成,反之則是讀取的文件內(nèi)容。

阻塞和非阻塞的切換與操作系統(tǒng)有關(guān),所以本篇暫時(shí)只寫了 Linux 版本。如果有過(guò) Unix 系統(tǒng)編程經(jīng)驗(yàn),會(huì)發(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 對(duì)象

Future 對(duì)象類似 Javascript 中的 Promise 對(duì)象。它是一個(gè)占位符,其值會(huì)在將來(lái)被計(jì)算出來(lái)。我們可以使用

result = await future

在 future 得到值之后返回。而使用

future.set_result(xxx)

就可以設(shè)置 future 的值,也意味著 future 可以被返回了。await 操作符會(huì)自動(dòng)調(diào)用 future.result() 來(lái)得到值。

loop.call_soon

通過(guò) loop.call_soon 方法可以將一個(gè)函數(shù)插入到事件循環(huán)中。

至此,我們的異步文件讀寫思路也就出來(lái)了。通過(guò) loop.call_soon 調(diào)用非阻塞讀寫文件的函數(shù)。若一次文件讀寫沒(méi)有完成,則計(jì)算剩余所學(xué)讀寫的字節(jié)數(shù),并再次插入事件循環(huán)直至讀寫完畢。

可以發(fā)現(xiàn)其就是把傳統(tǒng) Unix 編程里,非阻塞文件讀寫的 while 循環(huán)換成了 asyncio 的事件循環(huán)。

下面是這一過(guò)程的示意代碼。

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

更多關(guān)于Python中使用asyncio 封裝文件讀寫請(qǐng)關(guān)注PHP中文網(wǎng)(ipnx.cn)其他文章!    


Release Notes

Popular Entries