Python 多线程下载程序会无缘无故减慢速度

Python 多线程下载程序会无缘无故减慢速度,python,multithreading,multiprocessing,threadpool,python-multiprocessing,Python,Multithreading,Multiprocessing,Threadpool,Python Multiprocessing,我一直在使用Python中的请求和多处理.dummy开发一个多线程图像刮板 脚本运行良好,直到达到某一点。然后整个工作流程变得非常缓慢。而且,我使用的线程越多,我的体验就越早 下载部分看起来像: def download(URL): try: URL = URL.rstrip() down = requests.get(URL, headers={'x-test2': 'true'}) # Download Images

我一直在使用Python中的
请求
多处理.dummy
开发一个多线程图像刮板

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

下载部分看起来像:

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)   
穿线部分的外观如下所示:

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))
尝试一些不同但较大的最大值。这是您的代码在关闭池并打开另一个池之前将处理的URL列表中的数字元素

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


还有另外一件事要考虑…有些URL可能需要很长时间来处理,在代码运行一段时间后,许多线程可能会因为较慢的URL而陷入困境,从而使事情看起来总体上变慢。如果是这种情况,偶尔关闭线程池也无济于事。

您可以尝试偶尔关闭线程池,然后重新打开它。Python mp.Pool()存在一个问题,即如果您将池保持打开状态并进行较长时间/迭代,它将变慢。我不确定ThreadPool,但可以尝试一下。您有多少CPU内核?拥有比CPU多得多的线程并没有帮助。使用Python线程也无法获得真正的并行性,因为由于CPython的GIL(全局解释器锁),一次只能有一个线程运行Python代码。像这样的I/O绑定操作可能不会受到影响,但CPU绑定操作最好使用
多处理
而不是
线程
模块。@MarkTolonen我有6个内核,即使没有多个使用它们。我也经历过多处理的同样问题,但经过一些测试后,它似乎与
concurrent.futures'
一起工作,只是cpu使用率很高。@bivouac0你能解释一下如何存档吗?我是所有这些东西的初学者。一个池有
maxstasksperchild
选项。