при работе с aiohhtp загружаются не все URL - PullRequest
0 голосов
/ 09 апреля 2020

Я пытаюсь загрузить набор данных изображений с этого сайта . У них есть json файл с URL. Эти картинки действительно большие (4000 * 3000), поэтому синхронная загрузка для l oop и Image.open(urllib.request.urlopen(url)) была слишком медленной.

Именно поэтому я решил загрузить эти изображения асинхронно с asyncio и aiohttp. Я изменил некоторый учебный код с сайта aiohttp. Но проблема в том, что некоторые URL все еще не загружены. Они возвращают сообщение «ответьте, полезная нагрузка не загружена». Тем не менее, если я попытаюсь загрузить их снова (запустите свой сценарий еще раз), большинство этих URL-адресов будут загружены! И если я повторю этот процесс запуска моего сценария снова и снова - все изображения в конечном итоге будут загружены. Например, есть 6500 изображений. После первого запуска - 55 изображений остаются не загруженными. После второго запуска - 1. А после последнего загружаются все изображения.

У вас есть идеи, почему это может происходить?

from pathlib import Path
import json
from collections import defaultdict
import urllib
from matplotlib import pyplot as plt
import numpy as np
import aiohttp
import asyncio
import async_timeout
import aiofiles
import sys

async def fetch(session, tuple_):
    path_to_file, url = tuple_
    await asyncio.sleep(3)
    async with session.get(url, timeout=60*20) as resp:
        f = await aiofiles.open(path_to_file, mode='wb')
        t = await resp.read()
        await f.write(t)
        await f.close()
    return True

async def bound_fetch(sem, session, tuple_):
    async with sem:
        await fetch(session, tuple_)


async def fetch_all(session, urls, loop):
    sem = asyncio.Semaphore(100)
    results = await asyncio.gather(
        *[bound_fetch(sem, session, tuple_) for tuple_ in urls],
        return_exceptions=True  # default is false, that would raise
    )
    return results

async def main(args):
    print(args)
    path_to_json = Path(args[0])
    path_to_data = Path(args[1])
    path_to_data.mkdir(exist_ok=True)
    with open(path_to_json, 'r') as f:
        data = json.load(f)
    len_images = len(data['images'])

    urls = []
    for ind, img in enumerate(data['images']):
        path_to_file = path_to_data / img['file_name']
        if not path_to_file.exists() or path_to_file.lstat().st_size == 0:
            urls.append([path_to_file, img["microwork_url"]])

    print(len(urls))
    print(urls[0])

    timeout = aiohttp.ClientTimeout(total=0)
    async with aiohttp.ClientSession(loop=loop, timeout=timeout) as session:
        the_results = await fetch_all(session, urls, loop)

    with open('save_results.txt', 'w') as f:
        for l in the_results:
            f.write(str(l))
            f.write("\n")

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(sys.argv[1:]))
...