投稿したサンプル コードの 2 つの大きな問題は、非協調的であり、送信前にファイル全体をメモリにロードすることです。
while r != '':
r = fp.read(1024)
request.write(r)
Twisted は協調マルチタスキングを使用して、あらゆる種類の並行性を実現していることを思い出してください。したがって、このスニペットの最初の問題は、ファイル全体の内容に対する while ループであることです (これは大きいと言えます)。これは、ファイル全体がメモリに読み込まれ、プロセスで他の処理が発生する前に応答に書き込まれることを意味します。この場合、「何か」にはメモリ内バッファからネットワークへのバイトのプッシュも含まれるため、コードはファイル全体をメモリ内に一度に保持し、このループが完了したときにのみファイルの削除を開始します。 .
したがって、原則として、このようなループを使用して大きな仕事をする Twisted ベースのアプリケーションで使用するコードを作成するべきではありません。代わりに、イベント ループと連携する方法で、大きな仕事の各小さな部分を実行する必要があります。ネットワーク経由でファイルを送信する場合、これにアプローチする最良の方法は、プロデューサーとコンシューマーを使用することです。これらは、バッファ空イベントを使用して大量のデータを効率的に移動し、不当な量のメモリを浪費することなく移動するための関連する 2 つの API です。
これらの API のドキュメントは次の場所にあります。
http://twistedmatrix.com/projects/core/documentation/howto/producers.html
幸いなことに、この非常に一般的なケースのために、独自に実装するのではなく、使用できる作成済みのプロデューサーもあります。
http://twistedmatrix.com/documents/current/api/twisted.protocols.basic.FileSender.html
おそらく、次のように使用する必要があります。
from twisted.protocols.basic import FileSender
from twisted.python.log import err
from twisted.web.server import NOT_DONE_YET
class Something(Resource):
...
def render_GET(self, request):
request.setHeader('Content-Type', 'text/plain')
fp = open(fileName, 'rb')
d = FileSender().beginFileTransfer(fp, request)
def cbFinished(ignored):
fp.close()
request.finish()
d.addErrback(err).addCallback(cbFinished)
return NOT_DONE_YET
NOT_DONE_YET
私のブログhttp://jcalderone.livejournal.com/50562.htmlで、「Twisted Web in 60 Seconds」シリーズの詳細とその他の関連するアイデアを読むことができます(特に「非同期応答」エントリを参照してください)。