Одновременная загрузка и обработка больших файлов в Python

У меня есть список URL для загрузки больших файлов (например, сжатых архивов), которые я хочу обработать (например, распаковать архивы).

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

Это вариация проблемы производитель-потребитель.

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

Вот фиктивный пример, где загрузка и обработка блокируются:

import time
import posixpath

def download(urls):
    for url in urls:
        time.sleep(3)  # this is the download (more like 1000s) 
        yield posixpath.basename(url)

def process(fname):
    time.sleep(2)  # this is the processing part (more like 600s)

urls = ['a', 'b', 'c']
for fname in download(urls):
    process(fname)
    print(fname)

Как я могу сделать две задачи одновременно? Могу ли я использовать yield или же yield from умным способом, возможно, в сочетании с deque? Или это должно быть asyncio с Future?

2 ответа

Решение

Я бы просто использовал threading.Thread(target=process, args=(fname,)) и начать новый поток для обработки.

Но перед этим закончим последний поток обработки:

t = None
for fname in download(urls):
    if t is not None: # wait for last processing thread to end
        t.join()
    t = threading.Thread(target=process, args=(fname,))
    t.start()
    print('[i] thread started for %s' % fname)

См. https://docs.python.org/3/library/threading.html

Год спустя мы фактически используем Python 3 asyncio а также aiohttp,

Другие вопросы по тегам