在Twisted中更好的文件写入方式(阻塞IO操作)
我听说在Twisted框架中,我们应该避免输入输出(IO)阻塞操作。
但是如果我需要把接收到的数据导出到外部的txt文件呢?
现在我这样写我的代码,
有没有更好的解决方案呢?谢谢!
class BeginningPrinter(Protocol):
def __init__(self, finished):
self.finished = finished
self.counter = 0
def dataReceived(self, bytes):
self.counter += 1
f = open('export.txt', 'a')
f.write(bytes)
1 个回答
在使用Twisted时,尽量避免阻塞文件输入输出(I/O),原因和其他阻塞操作类似。任何一个线程一次只能做一件事。如果这个线程是反应器线程,而你让它去做的事情是等待某个操作完成,那么在这个操作完成之前,反应器分配给它的其他工作就无法进行。这会导致资源利用不充分和应用程序无响应。
当你的程序在网络输入输出上阻塞时,这个问题尤其严重,因为网络速度通常比较慢。更糟糕的是,网络另一端的程序可能并不总是可靠,甚至可能故意拖慢速度,特别是当它的操作者知道这样会对你的软件产生负面影响时。
磁盘输入输出的情况稍微不同。与网络相比,磁盘通常比较快(你的本地网络可能比磁盘快,但磁盘通常比公共互联网的随机连接快)。而且,磁盘通常不会恶意地让你的请求尽可能慢。因此,很多使用Twisted编写的程序认为文件系统操作“足够快”,并忽视了它们实际上是通过阻塞I/O来完成的。
不过,有些特殊情况可能需要你采取不同的方式。比如我曾经参与的一个项目,预期情况下,磁盘带宽几乎总是被同一台机器上运行的其他软件占满。这常常导致在使用Twisted的进程中,简单的文件系统操作需要几百毫秒甚至几千毫秒,这样的性能下降是不可接受的。在这种情况下,我们选择将文件系统操作移到第二个进程,并通过在UNIX套接字上运行的简单协议来驱动它们。
由于异步文件系统操作的工具相对原始,走这条路会增加不少额外的开发成本。在决定采取哪种方式之前,你应该考虑你的应用程序是否真的会受到在大多数正常情况下进行阻塞磁盘I/O时产生的1毫秒或2毫秒(或者更低,考虑到SSD的普及)等待时间的影响,或者你的软件是否需要在极端磁盘负载的情况下良好运行。