Python обрабатывает элементы из списка / очереди и сохраняет прогресс - PullRequest
0 голосов
/ 30 августа 2018

Если у меня есть около 10+ миллионов маленьких задач для обработки в Python (конвертирование изображений или около того), как я могу создать очередь и сохранить прогресс в случае сбоя при обработке. Чтобы было ясно, как я могу сохранить прогресс или остановить процесс, как захочу, и продолжить обработку с последней точки.

Также, как бороться с несколькими потоками в этом случае?

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

Спасибо!

(простите за мой английский, если он не понятен)

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

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

Самое простое - использовать многопоточность, а не многопроцессорность, и позволить планировщику ОС разобраться со всем этим. Документы имеют хорошее объяснение того, как настроить потоки. Простым примером будет

from threading import Thread

def process_data(file_name):
    # does the processing
    print(f'processed {file_name}')

if __name__ == '__main__':
    file_names = ['file_1', 'file_2']
    processes = [Thread(target=process_data, args=(file_name,)) for file_name in file_names]

    # here you start all the processes
    for proc in processes:
        proc.start()

    # here you wait for all processes to finish
    for proc in processes:
        proc.join()

Одним из решений, которое может быть быстрее, является создание отдельного процесса, который выполняет ввод / вывод. Затем вы используете multiprocessing.Queue, чтобы поставить в очередь файлы из «потока обработки данных», и позволить потоку ввода-вывода подобрать их и обработать их один за другим.

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

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

Не забудьте написать весь многопроцессорный код на Python в сценарии с

if __name__ == '__main__':
    # mp code

сторожите и помните, что некоторые IDE не очень хорошо работают с параллельным кодом Python. Безопасная ставка - проверить ваш код, выполнив его из терминала.

0 голосов
/ 30 августа 2018

Прежде всего я бы предложил не переходить на многопоточность. Вместо этого используйте мульти-обработку . Несколько потоков не работают синхронно в python из-за GIL, когда дело доходит до задач, требующих большого объема вычислений.

Для решения проблемы сохранения результата используйте следующую последовательность

  1. Получить имена всех файлов в списке и разделить список на куски.
  2. Теперь присвойте каждому процессу по одному куску.
  3. Добавлять имена обработанных файлов после каждых 1000 шагов к некоторому файлу (скажем, monitor.txt) в системе (при условии, что в случае сбоя вы можете снова обработать 1000 файлов).
  4. В случае сбоя пропустите все файлы, которые сохранены в файле monitor.txt для каждого процесса.

Вы можете использовать monitor_1.txt, monitor_2.txt ... для каждого процесса, поэтому вам не нужно будет читать весь файл для каждого процесса.

Следующие слова могут вам помочь. Вам просто нужно добавить код для 4-го пункта. https://gist.github.com/rishibarve/ccab04b9d53c0106c6c3f690089d0229

...