Как установить aiohttp ubuntu

Обновлено: 07.07.2024

Многие друзья находятся в состоянии "сильного слуха" асинхронного программирования. Он редко используется в производственных проектах. Большинство студентов, использующих его, остаются в асинхронных средах, которые знают, как использовать Tornado, Twisted и Gevent, и есть различные странные проблемы, которые трудно решить. И некоторые студенты, которые используют асинхронную среду, потому что использование не является правильным, я чувствую, что это не пугает, куда идти, поэтому многие студенты по-прежнему используют традиционные неасинхронные среды, такие как Flask и Django, при выполнении веб-сервисов.

На двух последних технологических конференциях PyCon асинхронное программирование стало главной темой следующего этапа экосистемы Python. Языки программирования, такие как развивающиеся Go, Rust, Elixir и т. Д., Рассматривают поддержку асинхронного и высокого параллелизма как свои основные «точки продажи», и это тенденция технологических изменений. После того, как экология Python не отстает, с 2013 года отец Python Гвидо лично руководил разработкой проекта Tulip (asyncio).

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

  • Ключевые моменты, которые необходимо знать об асинхронном вводе-выводе. Следует отметить, что синтаксис await может появляться только в функциях, измененных async, в противном случае он сообщит об ошибке SyntaxError. И объект, стоящий за await, должен быть ожидаемым или реализовывать соответствующий протокол.
  • Все функции, которые должны выполняться асинхронно, нуждаются в инструкторе в асинхронном режиме для выполнения обучения ротации.Если функция заблокирована, тренажер выполнит следующую функцию. Таким образом, все функции, которые должны выполняться асинхронно, должны быть добавлены к этому тренеру.

asyncio

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

Asyncio - это способ параллелизма. Для Python параллелизм также может быть достигнут с помощью многопоточности и многопоточности.

Asyncio не приносит истинного параллелизма. Конечно, из-за существования GIL (Global Interpreter Lock) многопоточность Python не может привести к истинному параллелизму.

Задачи, которые могут быть переданы asyncio для выполнения, называются сопрограммами. Сопрограмма может отказаться от выполнения и дать возможность другим сопрограммам (то есть уступить или ждать).

Определить сопрограммы

Определение сопрограмм требует использования async def операторов.

do_some_work Это сопрограмма. Точно, do_some_work Функция сопрограммы, которая может быть передана asyncio.iscoroutinefunction Проверять:

Эта сопрограмма ничего не сделала, мы оставляем ее на несколько секунд, чтобы имитировать фактическую нагрузку:

Прежде чем объяснить await, необходимо объяснить, на что способны сопрограммы. Сопрограммы могут:

  • В ожидании будущего до конца
  • Дождитесь другой сопрограммы (создайте результат или создайте исключение)
  • Дайте результат сопрограмме, которая его ждет
  • Вызывает исключение для сопрограммы, которая его ждет

asyncio.sleep Это также сопрограмма, так await asyncio.sleep(x) Просто жду другой сопрограммы. Смотрите документацию asyncio.sleep:

Запустить сопрограмму

Вызовите функцию сопрограммы, сопрограмма не запустится, просто верните объект сопрограммы, вы можете передать asyncio.iscoroutine Проверять:

Здесь также выдается предупреждение:

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

  • Используйте в другом уже запущенном сопрограмме await Ждать его
  • Через ensure_future Функция планирует его выполнение

run_until_complete Это блокирующий вызов, и он не возвращается, пока не завершится выполнение сопрограммы. Это нетрудно увидеть по названию функции.
run_until_complete Параметр S - это будущее, но здесь мы передаем ему объект сопрограммы. Причина, по которой он может это сделать, заключается в том, что он проверяет внутренне и ensure_future Функция переносит объект сопрограммы в будущее. Итак, мы можем написать более четко:

Перезвони

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

Несколько сопрограмм

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

Или сначала сохраните сопрограмму в списке:

Две сопрограммы выполняются одновременно, поэтому время ожидания составляет не 1 + 3 = 4 секунды, а более длинная сопрограмма.

Справочная функция gather Из документа:

Discovery также может передать ему фьючерс:

run_until_complete и run_forever

Мы прошли run_until_complete Чтобы запустить цикл и ждать, пока будущее не закончится, run_until_complete Это вернется.

Использовать сейчас run_forever :

Через три секунды будущее заканчивается, но программа не выходит. run_forever будет работать до тех пор, пока не будет вызван stop, но вы не можете вызвать stop следующим образом:

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

Это не без проблем, если в цикле работает несколько сопрограмм:

Вторая сопрограмма не закончилась, цикл прекратился - сопрограмма, которая закончилась первой, была остановлена.
Чтобы решить эту проблему, вы можете использовать команду collect для объединения нескольких сопрограмм в будущее, добавить обратный вызов и затем остановить цикл в обратном вызове.

На самом деле это в основном run_until_complete Был реализован, run_until_complete Внутренне также называется run_forever 。

Close Loop?

Ни один из приведенных выше примеров не называется loop.close Кажется, нет проблем. Итак, вы хотите настроить loop.close?
Короче говоря, пока цикл не закрыт, его можно запустить снова. :

Но если он закрыт, он больше не может быть запущен:

Рекомендуется вызывать loop.close для полной очистки объекта цикла во избежание неправильного использования.

gather vs. wait

asyncio.gather с участием asyncio.wait Функции похожи.

Конкретные различия можно найти в обсуждении StackOverflow:Asyncio.gather vs asyncio.wait。

Timer

C ++ Boost.Asio предоставляет таймеры для объектов ввода-вывода, но Python изначально не поддерживает таймеры, но его можно смоделировать с помощью asyncio.sleep.

Так называемые статические ресурсы относятся к файлам, таким как картинки, js и css.

Чтобы проиллюстрировать это небольшим проектом, ниже приведена структура каталогов проекта:

Добавьте маршруты к static / css и static / font в proxy_server.py:

2 обязательных параметра:

image.jpg

  • префикс: это префикс URL статического файла, начинающийся с /, он отображается в адресной строке браузера после хоста сайта, а также используется для статической страницы index.html для справки
  • path: путь к каталогу статических файлов, который может быть относительным путем. Static / css, использованный в приведенном выше коде, является относительным путем относительно пути, в котором находится proxy_server.py.

Загрузка index.html, вот код, который ссылается на статические ресурсы:

Путь для добавления шрифта потому, что нужно использовать /font-awesome.min.css:

Если вы измените префикс:

Хотя сам каталог все еще css, он был обработан как css2017 через add_static. Чтобы связать файлы с css в файлах и браузерах, вы должны использовать css2017 / xx.css для ссылки.

Кроме того, если вы добавите show_index = True, вы можете отобразить индекс каталога статического доступа к ресурсам по умолчанию:

image.jpg

Мульти-процесс + asyncio

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

Теперь демо реализовано несколько процессов, каждый процесс имеет асинхронное


Привет, меня зовут Артём и я работаю бекендером в KTS. Компания уже 3 года проводит летние и зимние курсы по разработке, а в феврале этого года прошла очередная бесплатная backend-школа от KTS. В ее рамках студенты изучали инструменты и технологии, которые используют разработчики нашей компании, общались с менторами и делали итоговый проект - чат-бота в стиле “Моя игра”, который защищали в конце курса. После курса отличившихся студентов мы приглашали на стажировку.

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

Студенты задавали достаточно разные по уровню понимания вопросы, начиная от “Как создать отложенную задачу, используя только asyncio?” и заканчивая “Почему нельзя использовать Django для асинхронного программирования?” (имелась в виду полностью синхронная версия Django). В коде наши менторы тоже находили ошибки, связанные с недостаточным пониманием предмета, например, использование синхронного драйвера для базы данных в асинхронном проекте.

В цикле статей мы рассмотрим следующие темы:

Асинхронная работа с базой данных и автоматические миграции

Работа с HTML-шаблонами с помощью Jinja2

Размещение нашего приложения в Интернете с помощью сервиса Heroku

А также сигналы, обработку ошибок, работу с Docker’ом и многое другое.


Мы пройдем по шагам:

Создание проекта

Все команды в статье были выполнены в операционной системе OSX, но также должны работать в любой *NIX системе, например в Linux Ubuntu. Во время разработки я буду использовать Python 3.7.

Создадим виртуальное окружение – что-то вроде песочницы, которое содержит приложение со своими библиотеками, обновление и изменение которых не затронет другие приложение, и установим в него наши зависимости:

После этого в начале строки терминала должна появится надпись (venv) — это означает что виртуальное окружение успешно активировано. Установим необходимые модули:

Структура проекта

Теперь откроем файл main.py и добавим в него следующее:

После предварительной настройки можно создать первый View.

Первый View

HTTP-ответ включает в себя полезную нагрузку, например, данные в json, заголовки и статус ответа. В простейшем View, который из примера выше, всю работу по формированию HTTP-ответа выполняет декоратор @aiohttp_jinja2.template("index.html") . Декоратор получает данные из View, которые возвращаются в виде словаря, находит шаблон index.html (о шаблонах написано ниже), подставляет туда данные из этого словаря, преобразует шаблон в html-текст и передает его в ответ на запрос. Браузер парсит html и показывает страницу с нашим контентом.

В файле views.py в папке app/forum напишем следующий код:

Здесь создается функциональный View (function-based View). Определение “функциональный” означает, что код оформлен в виде функции, а не классом (в следующей части мы коснемся и class-based View).

Отдельно стоит заметить, что объект запроса request передается как аргумент функции index. Мы не используем request в этой функции, но будем использовать в дальнейшем.

Первый Route

Route — это звено, связывающее адрес, по которому был отправлен запрос и код View, в котором этот запрос будет обработан. То есть, если пользователь перейдет в корень нашего сайта (по адресу /), то объект запроса будет передан в View index и оттуда же будет возвращен ответ. Подробней про Route можно прочитать тут.

В файл routes.py необходимо добавить следующий код:

Первый Template

Теперь нам осталось только добавить в templates/index.html код верстку нашей страницы. Его можно найти по этой ссылке.

Template — это html-шаблон, в который подставляются данные, полученные в результате обработки запроса. В примере в коде View отдается словарь с ключом title, шаблонизатор Jinja2 ищет в указанном html-шаблоне строки > и заменяет их на значение из словаря по данному ключу. Это простейший пример, шаблоны позволяют делать намного больше: выполнять операции ветвления, циклы и другие операции, например, суммирование. Примеры использования можно посмотреть в документации jinja2.

Запуск приложения

Вы должны увидеть следующий текст в консоли. Он означает, что сервер запущен на порту 8080.


Заключение

Настройку виртуального окружения

Весь код статьи можно найти на гитхабе.

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

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

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

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

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

В конце мы обсудим, как подготовить приложение к развертыванию в Хероку .

Введение в асинхронный Python

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

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

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

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

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

asyncio

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

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

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

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

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

Клиентская сторона: Выполнение Запросов

Несколько вещей, которые следует подчеркнуть:

  • Очень похоже на await asyncio.sleep мы должны использовать await with resp.text() для того, чтобы получить HTML-содержимое страницы. Если бы мы оставили это, результат нашей программы был бы примерно следующим:

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

Веб-приложение Planet Tracker

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

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

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

Планета Эфемерид с Пиефемом

Он особенно хорошо подходит для выполнения поставленной задачи, так как имеет общие астрономические объекты, приготовленные в библиотеке. Во-первых, давайте установим Пиефем :

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

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

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

Запуск этого фрагмента кода приведет к:

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

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

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

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

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

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

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

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

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

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

Клиент HTML/JavaScript

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

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

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

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

Тем не менее, файл JavaScript немного более вовлечен:

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

Хотя это не учебник по JavaScript, я думаю, что полезно понять, что делают различные части скрипта:

Праймер по развертыванию в Heroku

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

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

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

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

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

Вывод

После создания приложения мы подготовили его к развертыванию на Heroku.

Как уже упоминалось ранее, вы можете найти как исходный код , так и демо-версию приложения , если это необходимо.

Читайте также: