Aiohttp python что это
Перейти к содержимому

Aiohttp python что это

Руководство по созданию API-запросов в Python

Python сейчас переживает свой период возрождения. Собственно, он и не умирал, но сейчас степень его использования высока, как никогда раньше. Именно на этот язык полагаются разработчики машинного обучения и специалисты по обработке данных, а большая часть экосистемы веб-разработки вокруг этого языка продолжает расти.

Один из аспектов, влияющих на все три эти специализации, — мощные преимущества API. Сбор данных и подключение к внешним сервисам — важная часть любого языка. В этой статье мы рассмотрим основные библиотеки для выполнения HTTP-запросов, а также некоторые распространенные варианты их использования, позволяющие подключаться к API в Python. Но сначала следует ответить на один важный вопрос:

Подходит ли Python для API?

Это может показаться странным вопросом, но, учитывая засилье в вебе Node.js и Ruby, вы можете подумать, что Python не так хорош для создания API-запросов. Но это не так. На самом деле Python тоже давно присутствует в вебе, особенно если принять во внимание его библиотеки Flask и Django.

Поскольку Python предоставляет мощные и доступные инструменты для работы с данными, имеет смысл также использовать его и для получения самих источников данных. Для этого и служат запросы к API. Давайте начнем с самой популярной библиотеки Python под названием Requests.

Библиотека Requests

Requests — это широко известная библиотека, которую разработчики используют для выполнения API-запросов в Python. Она предлагает интерфейс для синхронного выполнения HTTP-запросов. Давайте рассмотрим несколько распространенных типов запросов, которые вы можете делать с помощью этой библиотеки. В дальнейшем мы будем предполагать, что эта библиотека у вас уже установлена. Для установки вы можете использовать документацию библиотеки, но сам процесс очень прост.

Библиотеку также нужно импортировать:

Распространенные типы API-запросов в библиотеке Requests

Наиболее простой GET-запрос интуитивно понятен:

По аналогии с приведенным выше примером метода get , библиотека Requests предлагает методы для всех HTTP-действий, а именно: POST, PUT, DELETE, HEAD и OPTIONS.

Этот запрос был довольно прост. Давайте теперь рассмотрим более сложные запросы. Часто документация по API требует, чтобы вы передавали параметры запроса в конкретную конечную точку. Чтобы это сделать, мы можем передать параметры запроса в метод get в качестве второго аргумента.

Переменная response содержит данные, возвращаемые API в качестве ответа на наш запрос. Есть три основных способа доступа к этим данным:

  • в виде текста, при помощи response.text ,
  • в виде байт-кода, при помощи response.content ,
  • в формате JSON, при помощи response.json() .

Также можно получить сырые данные при помощи response.raw .

Помимо тела самого ответа, мы также можем получить доступ к коду состояния — при помощи response.status_code , к заголовкам — при помощи response.headers , и так далее. Полный список атрибутов и методов, доступных для Response, вы можете найти в документации requests.Response .

Помимо параметров запроса, мы также можем передавать в запрос заголовки:

Здесь мы передаем в качестве аргумента заголовок в виде словаря Python.

Последний тип API-запроса, который мы сейчас рассмотрим — это полнофункциональный POST-запрос с аутентификацией. Этот пример объединит два предыдущих, здесь мы передадим в качестве аргументов и заголовок, и данные.

Здесь мы отправляем данные из переменной payload в формате словаря Python. Для большинства современных API нам часто требуется отправлять данные в формате JSON. В следующем примере мы используем встроенный json-конвертер из библиотеки Requests.

Это преобразует содержимое переменной payload в формат JSON, а также автоматически переведет в этот тип данных заголовки из переменной headers .

Библиотека Requests отлично подходит для выполнения синхронных API-запросов, но иногда вашему приложению нужно выполнять асинхронные запросы. Для этого мы можем использовать асинхронную HTTP-библиотеку aiohttp.

Библиотека aiohttp

Для выполнения асинхронных HTTP-запросов вам необходимо воспользоваться некоторыми новыми функциями Python 3. Хотя у библиотеки Requests есть различные дополнения и плагины для асинхронного программирования, одной из наиболее популярных библиотек для этого является библиотека aiohttp. Используя ее вместе с библиотекой acincio, мы можем эффективно исполнять асинхронные запросы. Код будет немного сложнее, но асинхронные запросы сами по себе предоставляют большую свободу действий.

Для начала установим библиотеку aiohttp:

Распространенные типы API-запросов в библиотеке aiohttp

Как и раньше, начнем с GET-запроса. Для начала импортируем обе библиотеки и определим функцию main() как асинхронную.

В этом коде мы выполняем следующие шаги:

  1. Импортируем необходимые библиотеки.
  2. Определяем функцию main как асинхронную.
  3. Устанавливаем сессию ClientSession из aiohttp.
  4. Используем данную сессию для выполнения HTTP GET-запроса.
  5. Далее дожидаемся ответа и выводим его на экран.
  6. Наконец, используем метод run из библиотеки asyncio для запуска асинхронной функции main() .

Если вы никогда раньше не работали с асинхронными методами в Python, это может показаться странным и сложным по сравнению с предыдущими примерами. Создатели библиотеки aiohttp рекомендуют устанавливать один сеанс для каждого приложения и открывать / закрывать соединения в этом сеансе. Чтобы сделать наши примеры самодостаточными, мы составили примеры в менее эффективном формате.

Далее давайте рассмотрим полнофункциональный POST-запрос с заголовками аутентификации, как мы сделали в примере для библиотеки Requests.

Между этим примером и предыдущим есть несколько различий:

  1. В нашей сессии используется метод post , который передает заголовки и словари json вместе с URL-адресом.
  2. Мы используем встроенный в библиотеку метод json из класса resp для анализа возвращенных данных в формате json.

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

Некоторые дополнительные библиотеки

Хотя библиотека Requests и является самой популярной и универсальной, в некоторых особых случаях вы можете найти полезными и другие библиотеки.

    : данная библиотека поддерживает как синхронные, так и асинхронные запросы. Она также использует API-интерфейс, совместимый с библиотекой Requests, что значительно упрощает переход между ними. В настоящее время библиотека находится в стадии бета-тестирования, но за ее развитием стоит последить. : интересный вариант, если вы сами создаете библиотеку. Эта библиотека низкоуровневая, поэтому вы можете создавать на нем свои собственные абстракции. Но если вам не нужна именно низкоуровневая библиотека, то сами создатели не рекомендуют ее использовать. : мы должны упомянуть urllib3 хотя бы потому, что это базовая библиотека, на которой построена библиотека Requests и многие другие очень известные библиотеки (например pip). Хотя urllib3 и менее удобна для пользователя, чем некоторые высокоуровневые библиотеки, она мощна и проверена на практике. Если по какой-то причине вам нужно что-то с меньшим количеством абстракций, чем в библиотеке Requests, urllib3 будет хорошим вариантом.

python books logo

Английский для программистов

Наш телеграм канал с тестами по английскому языку для программистов. Английский это часть карьеры программиста. Поэтому полезно заняться им уже сейчас

Асинхронное программирование для веб-разработки в Python

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

Python, как и многие другие языки, по умолчанию не является асинхронным. К счастью, быстрые изменения в мире ИТ позволяют нам писать асинхронный код даже с использованием языков, которые изначально не предназначались для этого. С годами требования к скорости превышают возможности оборудования, и компании по всему миру объединились с Reactive Manifesto для решения этой проблемы.

Неблокирующее поведение асинхронных программ может привести к значительному увеличению производительности в контексте веб-приложения, помогая решить проблему разработки реактивных приложений.

В Python 3 собраны несколько мощных инструментов для написания асинхронных приложений. В этой статье мы рассмотрим некоторые из этих инструментов, особенно в том, что касается веб-разработки.

Мы будем разрабатывать простое реактивное приложение на основе aiohttp для отображения текущих соответствующих небесных координат планет Солнечной системы с учетом географических координат пользователя.

Введение

Для тех, кто знаком с написанием традиционного кода Python, переход к асинхронному коду может быть концептуально немного сложным. Асинхронный код полагается на сопрограммы, которые в сочетании с циклом событий позволяют писать код, который может казаться выполняющим более одного действия одновременно.

Сопрограммы можно рассматривать как функции, у которых есть точки в коде, где они возвращают управление программой вызывающему контексту. Эти точки «доходности» позволяют приостанавливать и возобновлять выполнение сопрограмм в дополнение к обмену данными между контекстами.

Цикл событий решает, какой фрагмент кода запускается в любой момент – он отвечает за приостановку, возобновление и обмен данными между сопрограммами. Это означает, что части разных сопрограмм могут в конечном итоге выполняться в порядке, отличном от того, в котором они были запланированы. Идея выполнения различных фрагментов кода в произвольном порядке называется параллелизмом.

Размышление о параллелизме в контексте выполнения HTTP-запросов может прояснить ситуацию. Представьте, что вы хотите сделать много независимых запросов к серверу. Например, мы можем запросить веб-сайт, чтобы получить статистику обо всех спортивных игроках в данном сезоне.

Мы можем делать каждый запрос последовательно. Однако с каждым запросом мы можем представить, что наш код может некоторое время ждать, пока запрос будет доставлен на сервер, а ответ будет отправлен обратно.

Иногда эти операции могут длиться даже несколько секунд. Приложение может испытывать сетевую задержку из-за большого количества пользователей или просто из-за ограничений скорости данного сервера.

Что, если бы наш код мог делать другие вещи, ожидая ответа от сервера? Более того, что, если он вернется к обработке данного запроса только после получения данных ответа? Мы могли бы сделать много запросов в быстрой последовательности, если бы нам не приходилось ждать завершения каждого отдельного запроса, прежде чем переходить к следующему в списке.

Сопрограммы с циклом событий позволяют нам писать код, который ведет себя именно таким образом.

asyncio

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

В отличие от других языков асинхронного программирования, Python не заставляет нас использовать цикл событий, поставляемый с языком. Как указывает Бретт Кэннон, сопрограммы Python представляют собой асинхронный API, с которым мы можем использовать любой цикл событий. Существуют проекты, которые реализуют совершенно другой цикл обработки событий, например curio, или позволяют отбрасывать другую политику цикла событий для asyncio, например uvloop.

Давайте посмотрим на фрагмент кода, который одновременно запускает две сопрограммы, каждая из которых выводит сообщение через одну секунду:

Этот код выполняется примерно за 5 секунд, поскольку сопрограмма asyncio.sleep устанавливает точки, в которых цикл событий может перейти к выполнению другого кода. Более того, мы сказали циклу событий запланировать оба экземпляра wait_around для одновременного выполнения с функцией asyncio.gather.

asyncio.gather принимает список «ожидающих» и возвращает единственный объект asyncio.Task, который завершается только тогда, когда завершены все его составляющие задачи или сопрограммы. Последние две строки представляют собой шаблон asyncio для запуска данной сопрограммы до ее завершения.

Сопрограммы, в отличие от функций, не начинают выполняться сразу после вызова. Ключевое слово await – это то, что сообщает циклу событий запланировать выполнение сопрограммы.

Если мы удалим ожидание перед asyncio.sleep, программа завершится (почти) мгновенно, так как мы не сказали циклу событий на самом деле выполнить сопрограмму, которая в этом случае сообщает сопрограмме о приостановке на установленное количество время.

Поняв, как выглядит асинхронный код Python, давайте перейдем к асинхронной веб-разработке.

Установка aiohttp

aiohttp – это библиотека Python для выполнения асинхронных HTTP-запросов. Кроме того, он обеспечивает основу для сборки серверной части веб-приложения. Используя Python 3.5+ и pip, мы можем установить aiohttp:

В следующих примерах показано, как с помощью aiohttp загрузить HTML-содержимое веб-сайта example.com:

  • Как и в случае с await asyncio.sleep, мы должны использовать await с resp.text(), чтобы получить HTML-содержимое страницы. Если бы мы его не использовали, результат нашей программы был бы примерно таким:
  • async with – это менеджер контекста, который работает с сопрограммами вместо функций. В обоих случаях, когда он используется, мы можем представить, что внутри aiohttp закрывает соединения с серверами или иным образом освобождает ресурсы.
  • aiohttp.ClientSession имеет методы, соответствующие HTTP-глаголам. Точно так же, как session.get отправляет запрос GET, session.post отправляет запрос POST.

Этот пример сам по себе не дает преимущества в производительности по сравнению с синхронными HTTP-запросами. Настоящая красота клиентского aiohttp заключается в выполнении нескольких одновременных запросов:

Вместо того, чтобы делать каждый запрос последовательно, мы просим asyncio выполнять их одновременно с asycio.gather.

Веб-приложение PlanetTracker

В ходе этого раздела я намерен продемонстрировать, как собрать приложение, которое сообщает текущие координаты планет в небе в местоположении пользователя.

Пользователь указывает свое местоположение с помощью веб-API геолокации, который выполняет всю работу за нас.

В конце я покажу, как настроить Procfile для развертывания приложения на Heroku. Если вы планируете продолжить, пока я работаю над сборкой приложения, вы должны сделать следующее, предполагая, что у вас установлены Python 3.6 и pip:

PyEphem

PyEphem – это библиотека Python, которая позволяет точно вычислять эфемериды.

Он особенно хорошо подходит для поставленной задачи, так как в нем есть обычные астрономические объекты, приготовленные в библиотеке. Сначала установим PyEphem:

Получить текущие координаты Марса так же просто, как использовать экземпляр класса Observer для вычисления его координат:

Чтобы упростить получение эфемерид планет, давайте настроим класс PlanetTracker с методом, который возвращает текущий азимит и высоту данной планеты в градусах (PyEphem по умолчанию использует радианы, а не градусы для внутреннего представления углов):

Теперь мы можем довольно легко получить любую из семи других планет Солнечной системы:

Выполнение этого фрагмента кода даст:

aiohttp

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

Прежде чем мы сможем начать писать код, мы должны подумать о том, какие HTTP-команды мы хотим связать с каждой из этих задач. Для первой задачи имеет смысл использовать POST, так как мы устанавливаем географические координаты наблюдателя. Учитывая, что мы получаем эфемериды, имеет смысл использовать GET для второй задачи:

Здесь декоратор route.get указывает, что мы хотим, чтобы сопрограмма get_planet_ephmeris была обработчиком для маршрута GET переменной.

Прежде чем запустить это, давайте установим aiohttp с помощью pipenv:

Теперь мы можем запустить наше приложение:

Когда мы запускаем это, мы можем указать нашему браузеру разные маршруты, чтобы увидеть данные, которые возвращает наш сервер. Если я введу localhost: 8000/planets/mars в адресную строку браузера, я должен увидеть следующий ответ:

Это то же самое, что и следующая команда curl:

Если вы не знакомы с curl, это удобный инструмент командной строки, в том числе для тестирования ваших HTTP-маршрутов.

Мы можем предоставить URL-адрес GET для curl:

Это дает нам эфемериды Марса в Гринвичской обсерватории в Великобритании.

Мы можем закодировать координаты в URL-адресе запроса GET, чтобы мы могли получить эфемериды Марса в других местах (обратите внимание на кавычки вокруг URL-адреса):

curl также можно использовать для выполнения запросов POST:

Обратите внимание, что, предоставляя поле —data, curl автоматически предполагает, что мы делаем запрос POST.

Прежде чем мы продолжим, я должен отметить, что функция web.run_app запускает наше приложение блокирующим образом. Это определенно не то, чего мы хотим достичь.

Чтобы запустить его одновременно, нам нужно добавить еще немного кода:

Обратите внимание на наличие loop.run_forever вместо вызова loop.run_until_complete, который мы видели ранее. Вместо выполнения заданного количества сопрограмм мы хотим, чтобы наша программа запускала сервер, который будет обрабатывать запросы, пока мы не выйдем с помощью ctrl + c, после чего она корректно завершит работу сервера.

HTML и JavaScript

aiohttp позволяет нам обслуживать файлы HTML и JavaScript. Использование aiohttp для обслуживания «статических» ресурсов, таких как CSS и JavaScript, не рекомендуется, но для целей этого приложения это не должно быть проблемой.

Давайте добавим несколько строк в наш файл aiohttp_app.py для обслуживания HTML-файла, который ссылается на файл JavaScript:

Привет-сопрограмма настраивает маршрут GET на localhost: 8000/, который обслуживает содержимое index.html, расположенного в том же каталоге, из которого мы запускаем наш сервер.

Строка app.router.add_static устанавливает маршрут на localhost: 8000/ для обслуживания файлов в том же каталоге, из которого мы запускаем наш сервер. Это означает, что наш браузер сможет найти файл JavaScript, на который мы ссылаемся в index.html.

Примечание. В производственной среде имеет смысл переместить файлы HTML, CSS и JS в отдельный каталог, который обслуживается самостоятельно. Это делает так, что любопытный пользователь не может получить доступ к нашему серверному коду.

Файл HTML довольно прост:

Хотя файл JavaScript немного сложнее:

Это приложение будет периодически (каждые 2 секунды) обновлять и отображать эфемериды планет. Мы можем предоставить наши собственные географические координаты или позволить API геолокации в Интернете определить наше текущее местоположение. Приложение обновляет геолокацию, если пользователь перестает печатать на полсекунды или более.

  • createPlanetDisplay динамически создает элементы HTML и привязывает их к объектной модели документа (DOM).
  • updatePlanetDisplay принимает данные, полученные от сервера, и заполняет элементы, созданные createPlanetDisplay
  • get делает запрос GET к серверу. Объект XMLHttpRequest позволяет сделать это без перезагрузки страницы.
  • post отправляет POST-запрос на сервер. Как и в случае с get, это делается без перезагрузки страницы.
  • getGeoLocation использует API веб-геолокации для получения текущих географических координат пользователя. Это должно быть выполнено «в безопасном контексте» (т.е. мы должны использовать HTTPS, а не HTTP).
  • getPlanetEphemeris и getPlanetEphemerides отправляют GET-запросы к серверу, чтобы получить эфемериды для конкретной планеты и эфемериды для всех планет, соответственно.
  • testPerformance делает n запросов к серверу и определяет, сколько времени это займет.

Heroku

Heroku – это сервис для простого развертывания веб-приложений. Heroku заботится о настройке веб-компонентов приложения, например о настройке обратных прокси-серверов или о балансировке нагрузки. Heroku – отличный бесплатный хостинг для приложений, обрабатывающих небольшое количество запросов и небольшое количество пользователей.

В последние годы развертывание приложений Python в Heroku стало очень простым. По сути, мы должны создать два файла, в которых перечислены зависимости нашего приложения и сообщают Heroku, как запускать наше приложение.

Pipfile заботится о первом, а Procfile заботится о втором. Pipfile поддерживается с помощью pipenv – мы добавляем в наш Pipfile (и Pipfile.lock) каждый раз, когда устанавливаем зависимость.

Чтобы запустить наше приложение на Heroku, нам нужно добавить еще одну зависимость:

Мы можем создать наш собственный файл Procfile, добавив в него следующую строку:

По сути, это говорит Heroku использовать Gunicorn для запуска нашего приложения, используя специальный веб-воркер aiohttp.

Прежде чем вы сможете развернуть приложение в Heroku, вам нужно начать отслеживать приложение с помощью Git:

Обратите внимание, что вы можете пропустить этап «Подготовка приложения» в этом руководстве, так как у вас уже есть приложение, отслеживаемое git.

После развертывания приложения вы можете перейти к выбранному URL-адресу Heroku в своем браузере и просмотреть приложение, которое будет выглядеть примерно так:

URL-адресу Heroku

Заключение

В этой статье мы погрузились в то, как выглядит асинхронная веб-разработка на Python – ее преимущества и использование. Впоследствии мы создали простое реактивное приложение на основе aiohttp, которое динамически отображает текущие соответствующие координаты неба планет Солнечной системы с учетом географических координат пользователя.

После создания приложения мы подготовили его к развертыванию на Heroku. Как упоминалось ранее, при необходимости вы можете найти как исходный код, так и демонстрацию приложения.

Python и HTTP-клиенты

В настоящее время более чем вероятно, что вам придется написать HTTP-клиент для вашего приложения, который должен будет общаться с другим HTTP-сервером. Повсеместность REST API делает HTTP VIP персоной. Вот почему знание шаблонов оптимизации является обязательным условием.

В Python есть много HTTP-клиентов (библиотек); наиболее широко используемый и простой в работа с requests. Это стандарт де-фактора в наши дни.

Постоянные соединения

Первый способ, который необходимо принять во внимание, — это постоянное подключение к веб-серверу. Постоянные соединения являются стандартом начиная с HTTP 1.1, хотя многие приложения не используют их. Отсутствие оптимизации в нем легко объяснить, если вы знаете, что при использовании запросов в простом режиме (например, с функцией get) соединение закрывается при получение ответа от сервера. Чтобы избежать этого, приложению необходимо использовать объект Session, который позволяет повторно использовать уже открытое соединение.

Использование сеанса (Session) с запросами

Каждое соединение хранится в пуле соединений (по умолчанию помещает 10 соединений), размер пула также настраивается:

Изменение размера пула

Повторное использование TCP-соединения для отправки нескольких HTTP-запросов дает ряд преимуществ в производительности:

  • Снижение использования процессора и памяти (меньшее количество одновременно открытых соединений).
  • Уменьшенная задержка при последующих запросах (без TCP-handshaking).
  • Исключения могут быть подняты без штрафа закрытия TCP-соединения.

Протокол HTTP также обеспечивает конвейеризацию (pipelining), которая позволяет отправлять несколько запросов по одному и тому же соединению, не дожидаясь получения ответов (думаю, пакет). К сожалению, это не поддерживается библиотекой requests. Однако конвейеризация запросов может быть не такой быстрой, как их параллельная отправка. Так как, протокол HTTP 1.1 заставляет отправлять ответы в том же порядке, в котором были отправлены запросы — первым пришел — первым вышел.

Параллелизм

requests также имеют один существенный недостаток: эта библиотека синхронна. Вызов request.get («http://example.org») блокирует программу до тех пор, пока HTTP-сервер не ответит полностью. Недостатком может быть то, что приложение во время запроса ожидает ответа и ничего не делает. Вполне возможно, что программа могла бы делать что-то еще, а не сидеть без дела.

Интеллектуальное приложение может смягчить эту проблему, используя пул потоков, подобных тем, которые предоставляются concurrent.futures. Это позволяет очень быстро распараллеливать HTTP-запросы.

Использование futures с requests

Этот шаблон довольно полезен, он был упакован в библиотеку requests-futures. С помощью его можно легко использовать объект Session:

По умолчанию создается worker с двумя потоками, но программа может легко настроить это значение, передав аргумент max_workers или даже своего собственного исполнителя объекту FuturSession — например, так: FuturesSession (executor = ThreadPoolExecutor (max_workers = 10)).

Асинхронность

Как объяснялось ранее, requests полностью синхронен. Он блокирует приложение в ожидании ответа сервера, замедляя работу программы. Создание HTTP-запросов в потоках является одним из решений, но потоки имеют свои собственные накладные расходы, и это подразумевает параллелизм, который не всегда каждый рад видеть в программе.

Начиная с версии 3.5, Python предлагает асинхронность внутри своего ядра, используя aiohttp. Библиотека aiohttp предоставляет асинхронный HTTP-клиент, построенный поверх asyncio. Эта библиотека позволяет отправлять запросы последовательно, но не дожидаясь первого ответа, прежде чем отправлять новый. В отличие от конвейерной передачи HTTP, aiohttp отправляет запросы по нескольким соединениям параллельно, избегая проблемы, описанной ранее.

Использование aiohttp

Все эти решения (с использованием Session, thread, futures или asyncio) предлагают разные подходы к ускорению работы HTTP-клиентов. Но какая между ними разница с точки зрения производительности?

Производительность

Ниже приведен фрагмент HTTP-клиента, отправляющего запросы на httpbin.org, HTTP-API, который обеспечивает (среди прочего) конечную точку, имитирующую длинный запрос. Этот пример реализует все методы, перечисленные выше.

Программа для сравнения производительности использования различных запросов

Запуск этой программы дает следующий вывод:

Не удивительно, что более медленный результат приходит с сериализованной версией, поскольку все запросы выполняются один за другим без повторного использования соединения — 12 секунд на 10 запросов.

Использование объекта Session и, следовательно, повторное использование соединения означает экономию 8% времени, что уже является большим и легким выигрышем. Как минимум, вы всегда должны использовать Session.

Если ваша система и программа допускают использование потоков, рекомендуется использовать их для распараллеливания запросов. Однако у потоков есть некоторые накладные расходы, и они не менее весовые. Они должны быть созданы, запущены и затем присоединены.

Если вы не используете старые версии Python, то, без сомнения, использование aiohttp должно быть вашим выбором, если вы хотите написать быстрый и асинхронный HTTP-клиент. Это самое быстрое и масштабируемое решение, поскольку оно может обрабатывать сотни параллельных запросов.

Потоки

Еще одна эффективная оптимизация скорости — это потоковая передача запросов. При отправке запроса по умолчанию все тело ответа загружается немедленно. Лучший способ не загружать весь контент в память сразу при запросе. Для этого есть параметра stream, в библиотеке requests или атрибут content в aiohttp.

Потоковая передача с requests

Потоковая передача с aiohttp

Не загружать полный контент крайне важно, чтобы избежать ненужного выделения сотен мегабайт памяти. Если вашей программе не требуется доступ ко всему содержимому в целом, но она может работать с частями. Например, если вы собираетесь сохранить и записать содержимое в файл, чтение только куска и одновременная запись будет гораздо более эффективным, чем чтение всего тела HTTP, выделяя огромную кучу памяти , и только после этого записать его на диск.

Заключение

Я надеюсь, это статья облегчит вам выбор правильного HTTP-клиента и написание запросов с его помощью. Если вы знаете какую-либо другую полезную технику или метод, не стесняйтесь опишите ее в разделе комментариев ниже (можно в блоге автора статьи)!

Добавить комментарий

Ваш адрес email не будет опубликован.