python - 使用python,我应该将大数据缓存在数组中并一次写入文件吗?

标签 python io gevent

我一直有一个由 gevent 驱动的爬虫下载页面。爬虫采用生产者-消费者模式,我向队列提供这样的数据:{method:get, url:xxxx, other_info:yyyy}。

现在我想将一些响应组装到文件中。问题是,我不能在每个请求结束时打开并写入,这样的 io 成本很高,而且数据的顺序不正确。

我假设我应该对所有请求进行编号,按顺序缓存响应,打开一个greenlet来循环和组装文件,伪代码可能是这样的:

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个循环运行来等待缓存完成并写入不同的文件。

更新2

@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 在这方面确实很擅长),那么除了磁盘写入之外,这不应该消耗太多资源。如果这确实造成了问题,那么将文件分块读入内存(并按比例写入 block )可以大大减少这个问题,只要这可以作为文件上传的选项。

关于python - 使用python,我应该将大数据缓存在数组中并一次写入文件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19839646/

相关文章:

python - 为什么根据查询方式的不同,elasticsearch 报告的命中数会不同?

python - 使用极轴在 matplotlib 中进行四重显示

java - 如何将字节数组写入现有文件的一部分?

python - 如何使用 `gevent.pywsgi.WSGIServer` 和 `WebSocketHandler` 启用 Flask 应用程序的日志记录?

python - ubuntu 上的 lunatic-python/lupa 导入问题

python - 如何在完成解析之前退出模块?

java - 如果我可以保证我将同时读取/写入不同区域,是否可以同时读取/写入内存映射文件?

solaris - 多线程 printf 与 write(2) 缓冲

python - 将 concurrent.futures.Future 与 greenlets/gevent 一起使用

python - gevent.http.HTTPServer API 建议流式传输,而是缓冲整个请求和响应