Python使用延迟扭曲异步写入

Ken*_* Pu 2 python asynchronous twisted

关于Python Twisted框架,有人可以向我解释如何将非常大的数据字符串异步写入消费者,比如protocol.transport对象吗?

我想我缺少的是一个write(data_chunk)返回a 的函数Deferred.这就是我想做的事情:

data_block = get_lots_and_lots_data()
CHUNK_SIZE = 1024 # write 1-K at a time.
def write_chunk(data, i):
  d = transport.deferredWrite(data[i:i+CHUNK_SIZE])
  d.addCallback(write_chunk, data, i+1)
write_chunk(data, 0)
Run Code Online (Sandbox Code Playgroud)

但是,经过一天在Twisted API/Documentation中闲逛之后,我似乎无法找到类似deferredWrite等价物的东西.我错过了什么?

Gly*_*yph 8

正如让 - 保罗所说,你应该使用IProducer和IConsumer,但是你也应该注意到缺少deferredWrite这个有点故意遗漏.

首先,创建一个Deferred可能写入的每个字节的数据是一个性能问题:我们在web2项目中尝试了它,发现它是整个系统中最重要的性能问题,我们试图避免这个错误我们将web2代码移植到twisted.web.

然而,更重要的是,Deferredwrite"完成" 时返回的内容会产生误导性的印象:电线的另一端已收到您发送的数据.没有合理的方法来辨别这一点.代理,智能路由器,应用程序错误和各种网络设计都可能会让你误以为你的数据实际上已经到达了连接的另一端,即使它从未被处理过.如果您需要知道另一端已处理了您的数据,请确保您的应用程序协议具有仅在收到并处理数据后才会发送的确认消息.

在这种代码中使用生产者和消费者的主要原因是首先避免分配内存.如果你的代码确实将所有要写入其对等体的数据首先读入内存中的一个巨大的字符串(data_block = get_lots_and_lots_data()非常直接暗示了这一点),那么你就不会因此而失去太多transport.write(data_block).传输将唤醒并尽可能多地发送大量数据.此外,您可以简单地执行transport.write(hugeString),然后transport.loseConnection(),在所有数据都已发送或连接中断之前,传输实际上不会断开连接.(再说一次:如果你不等待确认,你就不会知道数据是否到达那里.但是如果你只是想将一些字节转储到套接字中而忘记它,那就可以了.)

如果get_lots_and_lots_data()实际上是在读取文件,则可以使用包含的FileSender类.如果它有点像文件但不完全一样,FileSender的实现可能是一个有用的例子.