类似的事情可以通过队列系统更好地处理,而不是每个线程具有自己的文件处理程序。这是因为由于每个线程都有自己的处理程序,因此在编写此文件时可能会遇到竞赛条件。
就资源而言,除了您的磁盘写入以外,这不应消耗太多资源,假设传递给文件的信息并不是很大(Python对此真的很好)。但是,如果确实存在问题,则在块中阅读记忆(以及在块中成比例地编写)可以大大减少此问题,只要可以作为文件上传的选项可用即可。
题
我一直都有一个Gevent Power crawler下载页面。爬行者采用生产者 - 消费者模式,我用这样的数据{方法:get,url:xxxx,shote_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对此真的很好)。但是,如果确实存在问题,则在块中阅读记忆(以及在块中成比例地编写)可以大大减少此问题,只要可以作为文件上传的选项可用即可。
其他提示
这取决于数据的大小。如果它很大,它可以放慢程序中所有结构中的结构。
如果内存不是问题,则应将结构保持在内存中,而不是从文件中读取。一次又一次使用并发请求打开文件不是一个好的解决方案。