【问题标题】:Concurrent download and processing of large files in pythonpython中大文件的并发下载和处理
【发布时间】:2017-01-30 07:57:47
【问题描述】:

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

下载和处理都需要很长时间,并且磁盘 IO 上的处理很繁重,所以我希望一次只运行一个。由于这两个任务花费大约相同的时间并且不竞争相同的资源,因此我想在处理最后一个文件时下载下一个文件。

这是 producer-consumer problem 的变体。

情况与reading and processing imagesdownloading loads of files 类似,但我的下载程序调用(还)不能picklable,所以我无法使用多处理,而且这两个任务花费的时间差不多。

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

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 in a smart way,或者与deque 结合使用吗?还是必须是asyncioFuture

【问题讨论】:

标签: python concurrency yield coroutine yield-from


【解决方案1】:

一年后,我们实际上正在使用 Python 3 的 asyncioaiohttp

【讨论】:

    【解决方案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

    【讨论】:

    • 酷,是的,这应该可以工作,而且实际上很简单。
    • 它确实应该,即使我编写了盲代码并且没有测试。如果有任何问题,请告诉我,以便我解决我的问题。
    • 我很确定这是一个可行的答案,但问题是我的代码在某些应用程序 (QGIS) 中运行,当我使用 python threading 时似乎不喜欢它(它崩溃了)。我必须调查细节,但基于协程的解决方案可能更安全。
    • 我认为t.join()for 循环的末尾丢失了。将其添加到 else 子句中。
    • 我确实导入了线程。我将在该应用程序之外尝试解决方案,并让您知道它是否有效。 @LaurentLAPORTE 似乎是对的。 @Loïc 你怎么说?
    猜你喜欢
    • 1970-01-01
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    相关资源
    最近更新 更多