私は常にGevent Powered Crawlerのダウンロードページを持っています。 Crawlerはプロデューサーと消費者のパターンを採用します。これは、このようなデータをキューにフィードします{Method:get、url:xxxx、other_info:yyyy}。
次に、いくつかの応答をファイルに組み立てたいと思います。問題は、リクエストが終了するたびに開いて書くことができないこと、IOコストがかかり、データが正しい順序でないことです。
すべてのリクエストを番号にし、応答を順番にキャッシュし、グリーンレットを開いてファイルをループして組み立てる必要があると思います。
max_chunk=1000
data=[]
def wait_and_assemble_file(): # a loop
while True:
if len(data)==28:
f= open('test.txt','a')
for d in data:
f.write(d)
f.close()
gevent.sleep(0)
def after_request(response, index): # Execute after every request ends
data[index]=response # every response is about 5-25k
より良い解決策はありますか?数千の同時リクエストがあり、メモリの使用が速すぎたり、一度にループが多すぎたり、予期せずにループが多すぎる可能性があるとは思いません。
アップデート:
上記のコードは、データのキャッシュとファイルの書き込みがどのように行われるかを示すだけです。実際の状況では、完全なファイルに完全なキャッシュを待つのを待つために、おそらく100ループが実行されます。
update2
@it ninjaはキューシステムを使用することを提案するので、Redisを使用して代替案を書きます。
def after_request(response, session_id, total_block_count ,index): # Execute after every request ends
redis.lpush(session_id, msgpack.packb({'index':index, 'content':response})) # save data to redid
redis.incr(session_id+':count')
if redis.get(session_id+':count') == total_block_count: # which means all data blocks are prepared
save(session_name)
def save(session_name):
data_array=[]
texts = redis.lrange(session_name,0,-1)
redis.delete(session_name)
redis.delete(session_name+':count')
for t in texts:
_d = msgpack.unpackb(t)
index = _d['index']
content = _d['content']
data_array[index]=content
r= open(session_name+'.txt','w')
[r.write(i) for i in data_array]
r.close()
もう少し良く見えますが、Redisで大きなデータを保存することが良い考えであるかどうかは疑問です。