【问题标题】:Python - Looping through large list and downloading images quicklyPython - 遍历大列表并快速下载图像
【发布时间】:2021-08-08 04:29:50
【问题描述】:

所以目前我有这个代码,它可以完美地按照我的预期工作。

import urllib.request
from tqdm import tqdm

with open("output.txt", "r") as file:
    itemIDS = [line.strip() for line in file]

x = 0

for length in tqdm(itemIDS):
    urllib.request.urlretrieve(
        "https://imagemocksite.com?id="+str(itemIDS[x]), 
        "images/"+str(itemIDS[x])+".jpg")
    x += 1

print("All images downloaded")

我四处寻找,发现的解决方案并不是我真正想要的。我有 200mbp/s,所以这不是我的问题。

我的问题是我的循环每秒迭代 1.1 - 1.57 次。我想加快速度,因为我有超过 5k 的图像要下载。它们每个也大约 1-5kb。

另外,如果有人有任何一般的代码提示,我将不胜感激!我正在学习python,它很有趣,所以我想尽可能地变得更好!

编辑: 使用下面关于 asyncio 的信息,我现在得到 1.7-2.1 It/s,哪个更好!可以更快吗?是不是我用错了?

import urllib.request
from tqdm import tqdm
import asyncio

with open("output.txt", "r") as file:
    itemIDS = [line.strip() for line in file]

async def download():
    x = 0
    for length in tqdm(itemIDS):
        await asyncio.sleep(1)
        urllib.request.urlretrieve(
            "https://imagemocksite.com?id="+str(itemIDS[x]), 
            "images/"+str(itemIDS[x])+".jpg")
        x += 1

asyncio.run(download())
print("All images downloaded")

【问题讨论】:

  • 如果服务器是瓶颈并且正在限制您的速率怎么办。那么你不能使循环更有效率。您或许可以通过多处理更快地下载图像。
  • 您不会为此使用 multiprocessing,而是使用 threading @Goion,因为这是一个 I/O 绑定任务,而不是 CPU 绑定
  • 正如@Goion 所说,它可能确实受到服务器的限制。补充他的后一条评论;通常asyncio 库(或具有类似功能的库,如 Tornado)用于这些类型的 I/O 应用程序,因为多处理更适合于繁重的计算。相比之下,asyncio 在单个进程和单个线程上运行,但可以“暂停”一个函数(等待它)并继续执行程序的其余部分,同时等待基于 Python 协程的输入。
  • mp、线程和异步都是不错的选择。除了个人选择之外,我认为没有任何理由选择其中一个。
  • 由于 GIL 的限制,我建议使用 mp。但是现在我认为多线程甚至异步都可以工作,因为大多数时候你无论如何都会等待。 Mp 可能只是浪费资源。

标签: python performance loops download


【解决方案1】:

评论已经提供了很好的建议,我认为您使用asyncio 是对的,这确实是用于此类工作的典型 Python 工具。

只是想提供一些帮助,因为您提供的代码并没有真正使用它的功能。

首先,您必须安装异步处理 HTTP 请求和本地文件系统 I/O 的 aiohttpaiofiles

然后,定义一个 download(item_id, session) 辅助协程,它根据其 item_id 下载单个图像。 session 将是 aiohttp.ClientSession,它是在 aiohttp 中运行异步 HTTP 请求的基类。

诀窍最终是拥有一个 download_all 协程,它同时在所有单独的 download() 协程上调用 asyncio.gatherasyncio.gather 是告诉asyncio“并行”运行多个协程的方式。

这应该会大大加快您的下载速度。如果不是,那么是第三方服务器限制了你。

import asyncio

import aiohttp
import aiofiles


with open("output.txt", "r") as file:
    itemIDS = [line.strip() for line in file]


async def download(item_id, session):
    url = "https://imagemocksite.com"
    filename = f"images/{item_id}.jpg"
    async with session.get(url, {"id": item_id}) as response:
        async with aiofiles.open(filename, "wb") as f:
            await f.write(await response.read())


async def download_all():
    async with aiohttp.ClientSession() as session:
        await asyncio.gather(
            *[download(item_id, session) for item_id in itemIDS]
        )


asyncio.run(download_all())
print("All images downloaded")

【讨论】:

    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    • 2014-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多