Используйте Python, должен ли я кэшировать большие данные в массиве и записать в файл один раз?

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

  •  28-07-2022
  •  | 
  •  

Вопрос

У меня все время есть страницы загрузки с питанием в Gevent. Crawler принимает шаблон производителя-потребителя, который я питаю очередью с такими данными {метод: get, url: xxxx, other_info: yyyy}.

Теперь я хочу собрать некоторый ответ в файлы. Проблема в том, что я не могу просто открыть и написать, когда каждый запрос заканчивается, что ввода -либо дорогостоящий, а данные не находятся в правильном порядке.

Я предполагаю, что я должен пронумеровать все запросы, отклик в кэше, откройте 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

Есть лучшее решение? Существуют тысячи одновременных запросов, и я сомневаюсь, что использование памяти может расти слишком быстро, или слишком много петли за один раз, или что -то неожиданно.

Обновлять:

Коды выше - это просто продемонстрировать, как выполняет кэширование данных и написание файлов. В практической ситуации, возможно, 1 сотню цикла запускается, чтобы дождаться завершения кэша и записать в разные файлы.

Обновление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 действительно хорош в этом). Если это создает проблему, прочитание в памяти файл кусочками (и пропорционально написание в кусках) может значительно уменьшить эту проблему, если это доступно в качестве опции для загрузки файлов.

Другие советы

Это зависит от размера данных. Если он очень большой, он может замедлить программу, имеющую всю структуру в памяти.

Если память не является проблемой, вы должны сохранить структуру в памяти вместо того, чтобы читать все время из файла. Откройте файл снова и снова с помощью запроса паралитов не является хорошим решением.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top