ブロック入出力を使用して大量のデータを取得するさまざまな関数があり、ストリーム/ファイルライクなオブジェクト(チャンクなど)を書くことができます。私はこのデータをクライアントに提供するために竜巻HTTPサーバーを持っています。私がメモリにすべてのデータを保存することができない限り、私はソースからそれを受け取っているので、クライアントにストリームする必要があります。だから私はそのようなことを書いた:Python Tornado HTTPサーバーでクライアントに関数をブロックした結果
import logging
logging.basicConfig(level=logging.DEBUG)
from concurrent.futures import ThreadPoolExecutor
from tornado import gen, httpserver, httpclient, web, ioloop, httputil, escape, locks, iostream
from threading import Event
def get_data(stream):
with open('/tmp/qq.dat') as file:
for chunk in iter(lambda: file.read(64*1024), b''):
stream.write(chunk)
class ProxyStream(object):
def __init__(self, request):
self._request = request
def write(self, data):
self._request.write(data)
event = Event()
self._request.flush(callback=lambda: event.set())
event.wait()
return len(data)
class Test(web.RequestHandler):
def initialize(self, workers):
self._workers = workers
@gen.coroutine
def get(self):
stream = ProxyStream(self)
yield self._workers.submit(get_data, stream)
logging.debug("GET done")
self.finish()
if __name__ == '__main__':
workers = ThreadPoolExecutor(4)
app = web.Application([
(r"/test", Test, {'workers': workers}),
])
server = httpserver.HTTPServer(app) server.bind(1488)
server.start(1)
ioloop.IOLoop.current().start()
それは、上記get_data()関数をコーディングし、いくつかのファイルを読み込み(それは非常に大きいかもしれない)と、引数として渡されたストリームにチャンクに書き込みます。ストリームは、受信データをRequestHandlerオブジェクトに書き込むProxyStreamオブジェクトによってエミュレートされ、チャンクがネットワークにフラッシュされるまで待機します。
このコードは予期したとおりに動作するようですが、この方法にはいくつかの落とし穴があるのか、それともこの問題を解決する良い方法があるのかという疑問があります。