У меня постоянно есть страницы загрузки поискового робота с питанием от gevent. Сканер использует шаблон производителя-потребителя, который я загружаю в очередь данными, подобными этому {method:get, url:xxxx, other_info:yyyy}.
Теперь я хочу собрать ответ в файлы. Проблема в том, что я не могу просто открыть и написать, когда каждый запрос заканчивается, это дорого и данные не в правильном порядке.
Я предполагаю, что я должен пронумеровать все запросы, кэшировать ответы по порядку, открыть гринлет для цикла и собрать файлы, псевдокод может быть таким:
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 — хорошая идея, надеюсь на дополнительные предложения!