Разделение асинхронных запросов и сохранение с помощью aiohttp

В настоящее время я много раз вызываю внешний API и загружаю содержимое ответа при каждом вызове. Я использую aiohttp и asyncio, чтобы ускорить этот процесс, но не могу понять, как отделить функции выборки от функций сохранения.

Настраивать

import asyncio
import os

from aiohttp import ClientSession

В настоящее время я использую следующую функцию:

async def fetch_and_save(link, path, client):
    async with await client.get(link) as response:
        contents = await response.read()

        if not os.path.exists(os.path.dirname(path)):
            os.makedirs(os.path.dirname(path))
        with open(path, "wb") as f:
            f.write(contents)

Мой основной вызов выглядит так:

async def fetch_and_save_all(inputs):
    async with ClientSession() as client:
        tasks = [asyncio.ensure_future(fetch_and_save(link, path, client))
                 for link, path in inputs]
        for f in asyncio.as_completed(tasks):
            await f


def main(inputs):
    loop = asyncio.get_event_loop()
    loop.run_until_complete(fetch_and_save_all(inputs))

if __name__ == "__main__":
    inputs = [
        (f"https://httpbin.org/range/{i}", f"./tmp/{i}.txt") for i in range(1, 10)]
    main(inputs)

Учитывая этот базовый пример, возможно ли разделить функции извлечения и сохранения в fetch_and_save?

Что именно вы имеете в виду под словом "отдельный"? Каков желаемый конечный результат или интерфейс? Конечно, можно просто вынести код сохранения в отдельную функцию, но я не думаю, что вы имеете в виду это.

sytech 22.12.2020 00:22

@sytech Мне действительно трудно издеваться над извлечением, и я думаю, что сохранение усложняет процесс.

Jack Moody 22.12.2020 00:31

Я понимаю. Разве простое перемещение соответствующего кода для извлечения и сохранения в их собственные функции не решит эту проблему? например fetch_and_save сделал бы что-то вроде await save(await fetch(...)) Тогда соответствующие функции могут быть смоделированы независимо.

sytech 22.12.2020 01:04
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Просто создайте независимые функции для fetch порции и save порции.

async def fetch(link, client):
    async with await client.get(link) as response:
        contents = await response.read()
    return contents

def save(contents, path):
    if not os.path.exists(os.path.dirname(path)):
        os.makedirs(os.path.dirname(path))
    with open(path, 'wb') as f:
        bytes_written = f.write(contents)
    return bytes_written

async def fetch_and_save(link, path, client):
    contents = await fetch(link, client)
    save(contents, path)

Другие вопросы по теме