pythonasyncio⽂件操作_Python中使⽤asyncio封装⽂件读写前⾔
和⽹络 IO ⼀样,⽂件读写同样是⼀个费事的操作。
默认情况下,Python 使⽤的是系统的阻塞读写。这意味着在 asyncio 中如果调⽤了
f = file('xx')
会阻塞事件循环。
本篇简述如何⽤ asyncio.Future 对象来封装⽂件的异步读写。
代码在 GitHub。⽬前仅⽀持 Linux。
阻塞和⾮阻塞
⾸先需要将⽂件的读写改为⾮阻塞的形式。在⾮阻塞情况下,每次调⽤ read 都会⽴即返回,如果返回值为空,则意味着⽂件操作还未完成,反之则是读取的⽂件内容。
linux怎么读文件内容
阻塞和⾮阻塞的切换与操作系统有关,所以本篇暂时只写了 Linux 版本。如果有过 Unix 系统编程经验,会发现 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 操作符会⾃动调⽤ sult() 来得到
值。
loop.call_soon
通过 loop.call_soon ⽅法可以将⼀个函数插⼊到事件循环中。
⾄此,我们的异步⽂件读写思路也就出来了。通过 loop.call_soon 调⽤⾮阻塞读写⽂件的函数。若⼀次⽂件读写没有完成,则计算剩余所学读写的字节数,并再次插⼊事件循环直⾄读写完毕。
可以发现其就是把传统 Unix 编程⾥,⾮阻塞⽂件读写的 while 循环换成了 asyncio 的事件循环。
下⾯是这⼀过程的⽰意代码。
def read_step(self, future, n, total):
res = ad(n)
if res is None:
self.loop.call_ad_step, future, n, total)
return
if not res: # EOF
future.set_result(bytes(self.rbuffer))
return
d(res)
self.loop.call_ad_step, future, self.BLOCK_SIZE, total)
def read(self, n=-1):
future = asyncio.Future(loop=self.loop)
self.rbuffer.clear()
self.loop.call_ad_step, future, min(self.BLOCK_SIZE, n), n) return future
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论