Пишем первое приложение на aiohttp: подготовка и запуск.
Привет! Меня зовут Артём, я работаю backend-разработчиком в KTS Studio. Недавно я вел лекцию в бесплатной школе python-разработки, дважды в год проходящей в нашей компании, и, в процессе подготовки материалов, получилась эта статья. Она рассчитана на студентов, которые прошли отбор на наши курсы, то есть на людей, которые уже имели небольшой опыт веб-разработки и умеют создавать на Python’е несложные программы. Приятного чтения!
Скорее всего мало кого удивит тот факт, что на Python’е можно написать свое веб-приложение. Такие слова как Flask и Django слышал почти каждый программист, хоть как-то связанный с Python или веб-программированием вообще. Эти фреймворки популярны, просты и достаточно производительны для большинства задач, возникающих при написании API или даже полноценного веб-приложения. Что же такое aiohttp и зачем нужен еще один веб-фреймворк на Python?
Как сказано в официальной документации:
Aiohttp — ассинхронный HTTP клиент и сервер, созданный для asyncio и Python
В чем же его преимущества перед более классическими Django и Flask? Одно из ключевых преимуществ указано в определении — он создан для asyncio, библиотеки для написания асинхронного кода на Python, в то время, как код на Django и Flask (традиционно) исполняется синхронно. То есть, веб-приложение на aiohttp в теории, а бенчмарки производительности лишь подтверждают эту теорию, может быть в несколько раз эффективнее такого же по функциональности приложения на Django или Flask.
Aiohttp позволяет создавать сложные веб-приложения, и, если судить по моему личному опыту, не уступает им по скорости разработки. Хорошая документация, примеры в сети и это руководство позволят быстро написать качественный и, что не менее важно, производительный сервис. Aiohttp в разработке используют такие компании как Yandex, Wargaming, Rambler и Skyscanner.
В конце каждой статьи будет ссылка на исходный код на github’е. В репозитории также хранится папка с необходимыми зависимостями venv/. Хранение зависимостей в репозитории в большинстве случаев неправильно, но в данном случае это сделано для немедленного запуска приложения. Если вы будете запускать приложение, скачанное из репозитория, не забудьте активировать виртуальное окружение командой source venv/bin/activate , выполненной в терминале из корня проекта.
Сегодня мы напишем небольшое веб-приложение на aiohttp — стену с отзывами, где каждый может оставить свое мнение о каком-то продукте. В процессе мы создадим расширяемую архитектуру веб-приложения на aiohttp, а также рассмотрим такие темы как:
- Архитектура веб-приложения
- Асинхронная работа с базой данных и автоматические миграции
- Работа с HTML-шаблонами с помощью Jinja2
- Размещение нашего приложения в Интернете с помощью сервиса Heroku
А также сигналы, обработку ошибок, работу с Docker’ом и многое другое.
Подготовка
Все команды в статье были выполнены в операционной системе OSX, но также должны работать в любой *NIX системе, например в Linux Ubuntu.
Во время разработки я буду использовать Python 3.7.
Давайте создадим папку aiohttp_server, которая в дальнейшем будет называться корень проекта, и в ней создадим текстовый файл requirements.txt, в который запишем необходимые зависимости:
Сохранив файл, откроем терминал и перейдем в нашу папку, чтобы скачать все необходимые зависимости:
После предпоследней команды в начале строки терминала должна появится надпись (venv) — это означает что виртуальное окружение успешно активировано. Дожидаемся загрузки всех модулей и идем дальше.
Первый запуск
Создадим в папке aiohttp_server следующую структуру:
Теперь откроем файл main.py и добавим в него следующее:
Зайдем в файл views.py в папке app/forum и напишем:
Только что мы создали функциональный View. Определение “функциональный” означает, что код оформлен в виде функции, а не в виде класса (в следующей части мы коснемся и class-based View).
Рассмотрим написанную функцию более детально.
Функция обернута в декоратор @aiohttp_jinja2.template("index.html") — этот декоратор передает возвращенное функцией значение в шаблонизатор Jinja2, а затем возвращает сгенерированную шаблонизатором html-страницу как http-ответ. В данном случае возвращенным значением является словарь, значения которого подставляются в html-файл index.html .
Отдельно стоит заметить, что объект запроса request передается как аргумент функции index . Мы не используем request в этой функции, но будем использовать в дальнейшем.
View — это некий вызываемый объект, который принимает на вход объект HTTP-запроса — Request и возвращает на пришедший запрос HTTP-ответ — Response.
Http-запрос содержит полезную информацию, например url, на который пришел запрос, данные, которые передал пользователь, а также контекст запроса. В контексте запроса содержатся данные, которые мы или aiohttp добавили к этому запросу. Например, мы предварительно авторизовали пользователя — чтобы повторно не проверять авторизацию пользователя из базы во всех View и не дублировать код, мы можем добавить объект пользователя в контекст запроса. Тогда мы сможем получить нашего пользователя во View примерно таким образом request['user'] , использовав хранилище запроса.
HTTP-ответ включает в себя полезную нагрузку, например json-данные, заголовки и статус ответа. В простейшем View, который мы только что написали, всю работу по формированию Http-ответа выполняет декоратор @aiohttp_jinja2.template("index.html") . Он получает данные из нашего View, которые мы возвращаем в виде словаря, находит шаблон index.html (о шаблонах написано ниже), подставляет туда данные из этого словаря, преобразует шаблон в html-текст и передает его в ответ на запрос. Браузер воспринимает html и показывает страницу с нашим контентом.
В файл routes.py необходимо добавить следующий код:
Route — это звено, связывающее адрес, по которому был отправлен запрос и код View, в котором этот запрос будет обработан. То есть если пользователь перейдет на корень нашего сайта (по адресу /), то объект запроса будет передан в View index и оттуда же будет возвращен ответ. Подробней про Route можно прочитать тут.
Осталось только добавить в templates/index.html код для визуального представления нашей страницы, его можно найти по этой ссылке.
Template — это некий html-код, в который можно подставить данные, полученные в результате обработки запроса. В данном случае, в коде View мы отдаем словарь с ключом title, фрейморк Jinja2 ищет в указанном html-шаблоне строки <
Мы создали первую версию нашего приложения! Осталось запустить его следующей командой в терминале (убедитесь, что находитесь в папке aiohttp_server):
Вы должны увидеть следующий текст:
Давайте теперь наконец-то посмотрим результаты нашей работы, для этого в браузере напишем в адресной строке http://0.0.0.0:8080 и нажмем Enter. Вы должны увидеть первую версию нашего приложения. При клике на кнопку “Отправить” должно возникнуть сообщение о том, что отзыв отправлен.
Поздравляю! Вы успешно создали первое приложение на aiohttp!
Резюме
Подведем итоги этой статьи:
- Настроили виртуальное python-окружение
- Создали базовую структуру проекта
- Написали первый View
- Поработали с Jinja2-шаблонами
- Провели первый запуск приложения
В следующей статье мы рассмотрим работу с базой данных и узнаем что такое миграции и как с ними удобнее работать в проектах с aiohttp.
Name already in use
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.rst
Async http client/server framework
- Supports both client and server side of HTTP protocol.
- Supports both client and server Web-Sockets out-of-the-box and avoids Callback Hell.
- Provides Web-server with middlewares and plugable routing.
To get something from the web:
An example using a simple server:
Feel free to make a Pull Request for adding your link to these pages!
We support Stack Overflow. Please add aiohttp tag to your question there.
Optionally you may install the cChardet and aiodns libraries (highly recommended for sake of speed).
Первые шаги в aiohttp
Привет, меня зовут Артём. Я работаю бэкендером в KTS и веду курсы по разработке в KTS Metaclass. Заметил, что труднее всего студентам даются темы по асинхронному программированию.
Основываясь на своём преподавательском опыте, я написал туториал, рассказывающий о создании базового aiohttp-сервиса с нуля и затрагивающий самые сложные для студентов вопросы: как сделать асинхронное python-приложение, как работать с базой данных и как разложить свой проект в интернете.
В цикле статей мы рассмотрим следующие темы:
Асинхронная работа с базой данных и автоматические миграции
Работа с HTML-шаблонами с помощью Jinja2
Размещение нашего приложения в Интернете с помощью сервиса Heroku
А также сигналы, обработку ошибок, работу с Docker и многое другое.
Эта статья – первая из трех, и ее цель — помочь начинающим aiohttp-программистам написать первое “hello-world” приложение.
В этой статье мы напишем небольшое веб-приложение на aiohttp — стену с отзывами, где пользователь может оставить мнение о продукте.

Мы пройдем по шагам:
Создание проекта
Все команды в статье были выполнены в операционной системе OSX, но также должны работать в любой *NIX системе, например в Linux Ubuntu. Во время разработки я буду использовать Python 3.7.
Давайте создадим папку aiohttp_server, которая в дальнейшем будет называться корнем проекта. В ней создадим текстовый файл requirements.txt, который будет содержать все необходимые для работы приложения зависимости и их версии. Запишем в него следующие модули:
Создадим виртуальное окружение – что-то вроде песочницы, которое содержит приложение со своими библиотеками, обновление и изменение которых не затронет другие приложение, и установим в него наши зависимости:
После этого в начале строки терминала должна появится надпись (venv) — это означает что виртуальное окружение успешно активировано. Установим необходимые модули:
Структура проекта
Создадим в папке aiohttp_server следующую структуру:
Теперь откроем файл main.py и добавим в него следующее:
После предварительной настройки можно создать первый View.
Первый View
View — это некий вызываемый объект, который принимает на вход HTTP-запрос — Request и возвращает на пришедший запрос HTTP-ответ — Response.
Http-запрос содержит полезную информацию, например url запроса и его контекст, переданные пользователем данные и многое другое. В контексте запроса содержатся данные, которые мы или aiohttp добавили к этому запросу. Например, мы предварительно авторизовали пользователя — чтобы повторно не проверять авторизацию пользователя из базы во всех View и не дублировать код, мы можем добавить объект пользователя в контекст запроса. Тогда мы сможем получить нашего пользователя во View, например, так: request[‘user’].
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).
Рассмотрим написанную функцию детальнее: функция обернута в декоратор @aiohttp_jinja2.template(«index.html») — этот декоратор передает возвращенное функцией значение в шаблонизатор Jinja2, а затем возвращает сгенерированную шаблонизатором html-страницу как http-ответ. В данном случае возвращенным значением будет словарь, значения которого подставляются в html-файл index.html.
Отдельно стоит заметить, что объект запроса request передается как аргумент функции index. Мы не используем request в этой функции, но будем использовать в дальнейшем.
HTTP-запрос отправляется на конкретный url-адрес. Для передачи HTTP-запроса в нужный View необходимо задать эту связь в приложении с помощью Route.
Первый Route
Route — это звено, связывающее адрес, по которому был отправлен запрос и код View, в котором этот запрос будет обработан. То есть, если пользователь перейдет в корень нашего сайта (по адресу /), то объект запроса будет передан в View index и оттуда же будет возвращен ответ. Подробней про Route можно прочитать тут.
В файл routes.py необходимо добавить следующий код:
Первый Template
Теперь нам осталось только добавить в templates/index.html код верстку нашей страницы. Его можно найти по этой ссылке.
Template — это html-шаблон, в который подставляются данные, полученные в результате обработки запроса. В примере в коде View отдается словарь с ключом title, шаблонизатор Jinja2 ищет в указанном html-шаблоне строки <
Запуск приложения
Мы создали первую версию нашего приложения! Осталось запустить его следующей командой в терминале (убедитесь, что находитесь в папке aiohttp_server):
Вы должны увидеть следующий текст в консоли. Он означает, что сервер запущен на порту 8080.
Давайте теперь посмотрим результаты нашей работы! Для этого перейдите по адресу http://0.0.0.0:8080 в браузере. Вы должны увидеть первую версию нашего приложения. При клике на кнопку “Отправить” должно возникнуть сообщение о том, что отзыв отправлен.

Поздравляю! Вы успешно создали первое приложение на aiohttp!
Заключение
В статье рассмотрено создание простого приложения на aiohttp, которое принимает запрос пользователя и отдает html-страницу. Мы затронули:
Настройку виртуального окружения
Базовую настройку проекта на aiohttp
Наше приложение представляет собой простой веб-сервер, отдающий html-страницу по запросу — в нем нет никакого взаимодействия с базами данных, его структура максимально проста и оно недоступно пользователям в Интернете. В следующих статьях мы разберем, как вырастить из нашей заготовки “настоящее” веб-приложение на aiohttp и опубликовать его в Интернете.
Весь код статьи можно найти на гитхабе.
Прочитать вторую статью из цикла «Asycnio для начинающих можно по ссылке»:
«Подключаем базу данных к приложению»
Асинхронное программирование на Python для джуниор-разработчиков
Асинхронное программирование используется для высоконагруженных проектов и микросервисов. Его спрашивают на собеседованиях в технологически развитых компаниях, и оно открывает дорогу к работе в интересных проектах. Если вы уже пишете на Python, но пока не изучили модуль Asyncio, приглашаю вас на курс по асинхронному программированию на Python. Четвёртый поток стартует 13 октября.
Разберётесь, как работает асинхронное программирование и где его лучше применять.
Получите опыт работы с микросервисами.
Освоите стандартную python-библиотеку Asyncio, напишите чат-бота и event loop.
Welcome to AIOHTTP¶
Asynchronous HTTP Client/Server for asyncio and Python.
Current version is 3.8.4.
Key Features¶
Supports both Server WebSockets and Client WebSockets out-of-the-box without the Callback Hell.
Web-server has Middlewares , Signals and plugable routing.
Library Installation¶
You may want to install optional cchardet library as faster replacement for charset-normalizer :
Note that the cchardet project is known not to support Python 3.10 or higher. See #6819 and GitHub: PyYoshi/cChardet/issues/77 for more details.
For speeding up DNS resolving by client API you may install aiodns as well. This option is highly recommended:
Installing speedups altogether¶
The following will get you aiohttp along with cchardet , aiodns and Brotli in one bundle. No need to type separate commands anymore!
Getting Started¶
Client example¶
Server example:¶
For more information please visit Client and Server pages.
What’s new in aiohttp 3?¶
Go to What’s new in aiohttp 3.0 page for aiohttp 3.0 major release changes.
Tutorial¶
Source code¶
The project is hosted on GitHub
Please feel free to file an issue on the bug tracker if you have found a bug or have some suggestion in order to improve the library.
The library uses Azure Pipelines for Continuous Integration.
Dependencies¶
Install it explicitly via:
Optional aiodns for fast DNS resolving. The library is highly recommended.
Communication channels¶
Feel free to post your questions and ideas here.
We support Stack Overflow. Please add aiohttp tag to your question there.
Contributing¶
Please read the instructions for contributors before making a Pull Request.
Authors and License¶
The aiohttp package is written mostly by Nikolay Kim and Andrew Svetlov.
It’s Apache 2 licensed and freely available.
Feel free to improve this package and send a pull request to GitHub.
Policy for Backward Incompatible Changes¶
aiohttp keeps backward compatibility.
After deprecating some Public API (method, class, function argument, etc.) the library guaranties the usage of deprecated API is still allowed at least for a year and half after publishing new release with deprecation.
All deprecations are reflected in documentation and raises DeprecationWarning .
Sometimes we are forced to break the own rule for sake of very strong reason. Most likely the reason is a critical bug which cannot be solved without major API change, but we are working hard for keeping these changes as rare as possible.