多线程下载器无缘无故变慢

Multithreaded downloader slows down for no reason

我一直在使用 requestsmultiprocessing.dummy 在 Python 开发多线程图像抓取工具。

脚本运行良好,直到达到某个点。然后整个工作流程变得非常缓慢。而且似乎我使用的线程越多,我越早体验到这一点。

下载部分看起来像:

def download(URL):
    try:
        URL = URL.rstrip()    
        down = requests.get(URL, headers={'x-test2': 'true'})
        # Download Images 

    except BaseException as e:
        print("Error")

线程部分看起来像:

if __name__ == '__main__':
    ThreadPool(20).map(download, URLlist)   

所以我的问题是,是什么减慢了我的整个下载过程,因为 url 很好,它应该像以前一样继续。有没有我遗漏的命令,或者它与我的线程部分有关? (线程未正确关闭...)

同样重要的是,较小的 url 列表不会出现此问题。

(但这不应该是我从中下载的页面的请求限制问题,因为同时脚本是 运行 并且在我遇到页面速度和可用性方面的 0 个问题之后)。这是为什么?

如果池操作在一段时间内变慢,那么经常关闭池可能(或可能不会)有所帮助。尝试像这样简单的事情...

if __name__ == '__main__':
    max_size = # use some large value here
    for i in range(0, len(URLlist), max_size):
        st = time.time()
        pool = ThreadPool(20)    
        pool.map(download, URLlist[i: i + max_size])
        pool.close()    # should not be needed in practice
        pool.join()
        et = time.time()
        print('Processing took %.3f seconds' % (et-st))

为 max_size 尝试一些不同但较大的值。这是您的代码在关闭池并打开另一个池之前将处理的 URLlist 中的数字元素。

正如我在评论中所说,我知道 multiprocessing.Pool() 存在这个问题,但我不确定 ThreadPool() 是否存在同样的问题。对于 mp.Pool(),这只会发生在要处理的项目列表非常大的情况下。发生这种情况时,您通常会看到内存使用量随着程序运行而不断增加(因此请注意这一点)。我认为潜在的问题是池工作人员被一遍又一遍地创建,但在您关闭池之前没有正确地进行垃圾收集。

还有一件事要考虑...有些 URL 可能需要很长时间才能处理,并且在您的代码运行一段时间后,您的许多线程可能会因较慢的 URL 而陷入困境,从而使事情出现整体放缓。如果是这样的话,偶尔关闭池也无济于事。