关于并发:在python中同时下载和处理大文件

Concurrent download and processing of large files in python

我有一个大型文件下载的URL列表(例如压缩的档案),我想处理它(例如解压缩档案)。

下载和处理都需要很长时间,而且磁盘IO的处理量很大,所以我希望一次只运行一个。由于这两个任务占用的时间大致相同,并且不会争夺相同的资源,所以我希望在处理最后一个文件时下载下一个文件。

这是生产者-消费者问题的一个变种。

这种情况类似于读取和处理图像或下载文件的负载,但我的下载程序调用尚未被拾取,因此我无法使用多处理,而且这两个任务的时间大致相同。

下面是一个虚拟示例,其中下载和处理都被阻塞:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)

如何使这两个任务并发?我能以一种聪明的方式使用yieldyield from,也许与deque结合使用吗?或者必须是asyncioFuture一起?


一年后,我们实际使用的是python 3的asyncioaiohttp


我只需要使用threading.Thread(target=process, args=(fname,))并启动一个新的线程进行处理。

但在此之前,结束最后一个处理线程:

1
2
3
4
5
6
7
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