Pythonを使用して、アレイの大規模なデータをキャッシュし、1回ファイルに書き込む必要がありますか?

StackOverflow https://stackoverflow.com/questions/19839646

  •  28-07-2022
  •  | 
  •  

質問

私は常に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で大きなデータを保存することが良い考えであるかどうかは疑問です。

役に立ちましたか?

解決

このようなものは、各スレッドが独自のファイルハンドラーを持っている代わりに、キューシステムでより適切に処理することができます。これは、各スレッドが独自のハンドラーを持っているため、このファイルを書くときにレース条件に遭遇する可能性があるためです。

リソースに関する限り、これはディスクに渡されている情報が非常に大きくないと仮定して、ディスクの書き込み以外のリソースを消費するべきではありません(Pythonはこれについて本当に良いことです)。しかし、これが問題をもたらす場合、これがファイルアップロードのオプションとして利用可能である限り、チャンクのファイルをメモリに読み込むことがこの問題を大幅に減らすことができます。

他のヒント

データのサイズに依存します。それが非常に大きい場合は、すべての構造をメモリにするプログラムを遅くすることができます。

メモリが問題でない場合は、ファイルから常に読み取るのではなく、構造をメモリに保持する必要があります。同時リクエストで何度も何度もファイルを開くことは、良い解決策ではありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top