多线程下载器无缘无故变慢
Multithreaded downloader slows down for no reason
我一直在使用 requests
和 multiprocessing.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 而陷入困境,从而使事情出现整体放缓。如果是这样的话,偶尔关闭池也无济于事。
我一直在使用 requests
和 multiprocessing.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 而陷入困境,从而使事情出现整体放缓。如果是这样的话,偶尔关闭池也无济于事。