Как создать и развернуть приложение на Python?
Python – это свободный язык программирования с открытым исходным кодом, который имеет множество применений. Он был создан Гвидо Ван Россумом в 1991 году и с тех пор превратился в один из самых популярных языков программирования.
В этой статье мы расскажем о Python, его преимуществах, недостатках, вариантах использования и развертывания. Кроме того, мы продемонстрируем, как собрать, докеризировать и развернуть простое Python-приложение в контейнерах Back4app.
Продолжайте читать, чтобы узнать, как собрать и развернуть проект на Python.
Contents
Обзор Python
Python – это высокоуровневый язык программирования общего назначения. Он является интерпретируемым, динамически типизированным и может использоваться как для написания сценариев, так и для программирования. Разработчики обычно описывают Python как язык с “батарейками в комплекте” благодаря обширной стандартной библиотеке.
Язык впервые появился в 1991 году и с тех пор стал одним из самых популярных и любимых языков программирования благодаря своему простому и легко читаемому синтаксису. Основные принципы проектирования Python описаны в книге The Zen of Python, написанной Тимом Питерсом.
У Python огромное сообщество разработчиков и готовые к использованию пакеты. В наши дни Python используется практически везде – в администрировании серверов, научных вычислениях, машинном обучении, создании RESTful API и так далее. Python можно считать одним из важнейших навыков современного разработчика.
Преимущества Python
Простота в использовании
Python – один из самых простых в использовании и изучении языков. Его кривая обучения практически отсутствует, потому что основная философия дизайна делает упор на простоту и читабельность кода. Python также популярен в образовании, поскольку это отличный инструмент для изучения основных концепций программирования.
Быстрое развитие
Еще одно достоинство Python – возможность быстрой разработки. Это отличный язык для создания прототипов и быстрого завершения работы. Используя Python, вам не нужно беспокоиться о сложном синтаксисе, распределении памяти и так далее, вместо этого вы можете сосредоточиться на своем приложении.
Универсальный
Python – один из самых универсальных языков программирования. Он используется в самых разных отраслях и сферах. Некоторые из областей, в которых используется Python, включают бухгалтерский учет, научные исследования, науку о данных, веб-разработку, разработку игр и автоматизацию.
Портативный
Python – переносимый язык, поскольку он интерпретируется (как Java), а не компилируется (как C++). Это означает, что код, написанный на одной платформе, может быть легко перенесен на другую. Это делает Python популярным выбором для разработчиков, которым необходимо поддерживать несколько платформ, включая Windows, macOS, Linux и Android.
Обширные библиотеки
Язык программирования Python опирается на огромное сообщество разработчиков. В нем есть библиотека практически для всего, что вы можете себе представить. Некоторые из самых популярных библиотек включают:
- Веб-разработка(Django, Flask, FastAPI)
- Машинное обучение и наука о данных(TensorFlow, PyTorch)
- Компьютерное зрение(OpenCV, Pillow, Scikit-image)
- Научные вычисления(NumPy, SciPy)
- Графический интерфейс пользователя(Qt, GTK)
И это лишь малая часть. Если вы хотите посмотреть полный список удивительных пакетов Python, загляните на awesome-python на GitHub.
Динамически типизированные
Python – динамически типизированный язык, что означает, что вам не нужно объявлять тип данных при создании переменных. Тип переменной присваивается только во время выполнения кода.
Как бы это ни было здорово, динамически типизированные языки иногда могут быть обоюдоострым мечом. Они обычно более склонны к ошибкам и имеют более низкий уровень контроля памяти по сравнению со статически типизированными языками.
Расширяемый
Если требования вашего проекта включают в себя задачи с тяжелыми вычислениями, вы можете написать их на более быстрых языках, таких как C или C++, а затем вызвать их из кода Python.
Чтобы узнать больше о вызове C/C++ из Python, ознакомьтесь с этой замечательной статьей.
Ограничения Python
Плохое представление
Python относительно медленный язык по сравнению с другими языками программирования. Два фактора, которые в наибольшей степени снижают его производительность, – это то, что Python является интерпретируемым языком и динамически типизированным. Если требования вашего проекта включают тяжелые вычисления или многопоточность, Python может оказаться не самым подходящим инструментом. Вам будет гораздо лучше использовать C, C++ или другой компилируемый язык.
Интенсивная память
Программы на Python по сравнению с программами, написанными на статически-типизированных языках, обычно потребляют больше памяти и обеспечивают более низкий уровень контроля над памятью. Это может быть несколько проблематично, если ваши приложения должны быть эффективными с точки зрения использования памяти.
Склонность к ошибкам во время выполнения
Python, будучи интерпретируемым языком, более подвержен ошибкам во время выполнения. Поскольку в нем нет процесса компиляции, ошибки не могут быть обнаружены во время компиляции. Кроме того, Python динамически типизирован, что означает, что разработчик может изменить тип переменной в любой момент. Это иногда приводит к ошибкам и требует от разработчиков внимательного отношения к типам переменных.
Глобальная блокировка переводчика (GIL)
Глобальная блокировка интерпретатора (GIL) в Python – это механизм, который обеспечивает одновременное выполнение байткода Python только одним потоком. Хотя это упрощает реализацию языка и дает некоторый выигрыш в производительности для определенных типов программ, это также ограничивает возможность полностью использовать многоядерные процессоры в приложениях с привязкой к CPU.
Не оптимизирован для доступа к базам данных
Работа с базами данных в приложениях на Python может быть более сложной из-за отсутствия мощных и удобных интерфейсов, таких как Java Database Connectivity (JDBC). Хотя Python все еще можно использовать для операций с базами данных, включающих простые задачи чтения и записи, он может оказаться не самым подходящим вариантом для приложений, которым необходимо работать с большими и сложными базами данных.
Варианты развертывания Python
Python-приложения могут быть развернуты на нескольких облачных платформах. В целом их можно разделить на следующие три категории:
- Инфраструктура как услуга (IaaS)
- Платформа как услуга (PaaS)
- Контейнеры как услуга (CaaS)
IaaS – наименее абстрагированный, а CaaS – наиболее абстрагированный. Существует также обычный хостинг, но я уверен, что вы с ним уже знакомы.
Инфраструктура как услуга (IaaS)
Инфраструктура как услуга или IaaS – это модель облачных вычислений, при которой сторонний поставщик предлагает виртуализированные вычислительные ресурсы, такие как серверы, системы хранения данных, операционные системы и сети через Интернет. Предоставленными ресурсами можно управлять с помощью расширенных панелей управления или высокоуровневых API, предоставляя клиентам полный контроль над всей инфраструктурой.
Основными преимуществами IaaS являются масштабируемость, экономия средств, расширенная поддержка, производительность и безопасность. Структура оплаты, принятая большинством провайдеров IaaS, основана на системе “плати по мере использования”, когда вы платите только за используемые ресурсы.
IaaS – самая гибкая модель облачных вычислений, которая остается наиболее популярной с момента своего появления в начале 2010-х годов. Ее главный недостаток заключается в том, что клиент несет полную ответственность за свои приложения, операционные системы и данные.
Платформа как услуга (PaaS)
Платформа как услуга (PaaS) – это услуга облачных вычислений, которая предоставляет пользователям облачную среду для создания, управления и доставки приложений. PaaS предлагает готовые инструменты для разработки, настройки и тестирования приложений. Благодаря PaaS пользователи могут сосредоточиться на своем приложении, поскольку поставщик услуг позаботится о базовой инфраструктуре, включая серверы, операционные системы, программное обеспечение, резервное копирование и многое другое.
К преимуществам PaaS относятся ускоренный выход на рынок, повышенная безопасность, экономическая эффективность, масштабируемость, высокая доступность и, как правило, меньший объем кода. Однако есть и несколько минусов. Основные три минуса – отсутствие гибкости, отсутствие контроля и риск привязки к поставщику. Тем не менее PaaS позволяет пользователям создавать приложения быстрее и с меньшими затратами на управление.
Контейнеры как услуга (CaaS)
Контейнеры как услуга (CaaS) – это модель облачных вычислений, которая позволяет организациям загружать, запускать, масштабировать и управлять контейнерами с помощью технологии виртуализации контейнеров. Поставщики CaaS абстрагируются от большей части необходимой работы, такой как инфраструктура, операционные системы, программное обеспечение, механизмы контейнеризации и многое другое.
Самое замечательное в контейнерах то, что если ваше приложение контейнеризировано, вы можете развернуть его практически в любом месте, и оно гарантированно будет вести себя одинаково. Если возникнет необходимость, вы можете перейти от одного поставщика CaaS к другому. Клиентам CaaS обычно выставляют счет за контейнер (в зависимости от спецификации контейнера).
CaaS обычно дороже IaaS и PaaS, предлагает меньший уровень гибкости и контроля, а также требует некоторой первоначальной работы, например, докеризации приложения и так далее. Тем не менее, это одна из самых простых моделей облачных вычислений, которую можно использовать после того, как ваше приложение будет контейнеризировано.
Чтобы узнать больше о контейнерах, прочитайте статью Что такое контейнеры в облачных вычислениях?
Процесс развертывания Python
В этой части учебника мы шаг за шагом покажем, как создать и развернуть простое приложение на Python. Веб-приложение будет реализовано с помощью фреймворка Flask и развернуто на Back4app Containers.
Пререквизиты
- Опыт работы с Python и Flask
- Базовое понимание Docker
- Python версии 3.8 или более поздней и установленный Docker Desktop
Что такое Back4app Containers?
Back4app Containers – это бесплатная платформа с открытым исходным кодом, которая позволяет развертывать и масштабировать приложения с помощью глобально распределенных контейнеров.
С контейнерами Back4app вы можете сосредоточиться на создании своего программного обеспечения и его быстрой доставке, не заботясь о DevOps.
Платформа тесно интегрирована с GitHub и оснащена встроенной системой CI/CD. Используя Back4app Containers, вы сможете вывести свое приложение в сеть за считанные минуты.
Зачем использовать контейнеры Back4app?
- Хорошо интегрируется с GitHub
- Масштабирование и развертывание с нулевым временем простоя
- Чрезвычайно прост в использовании
- Отличная поддержка клиентов
Введение в проект
В этой статье мы создадим и развернем простой RESTful API, который будет служить в качестве списка TODO. Веб-интерфейс позволит пользователям выполнять основные CRUD-операции – такие как добавление задач, удаление задач, пометка их как выполненных и так далее.
Сначала мы поработаем над исходным кодом, а затем развернем его в Flask-контейнере Back4app. Веб-приложение будет реализовано с помощью веб-фреймворка Flask.
Не стесняйтесь пропустить раздел “Код приложения” и продолжить работу над собственным проектом на Python.
Код приложения
Проект “Инит
Начните с создания специального каталога для приложения Flask и перейдите в него:
$ mkdir flask-todo
$ cd flask-todo
Создайте виртуальную среду и активируйте ее:
$ python3 -m venv venv && source venv/bin/activate
Затем установите Flask с помощью pip:
$ (venv) pip install Flask==2.2.2
Чтобы убедиться, что все работает, давайте заменим содержимое app.py на следующее:
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index_view():
return {
'detail': 'Hello world'
}
Этот код инициализирует Flask и создает простую конечную точку, которая возвращает сообщение.
Запустите сервер с помощью:
$ (venv) flask run
Наконец, перейдите по адресу http://localhost:5000/ в вашем любимом браузере. Вы должны увидеть сообщение Hello world
.
База данных
Двигаясь дальше, давайте разберемся с базой данных.
Вместо того чтобы выполнять необработанный SQL, мы будем использовать Flask-SQLAlchemy – простой ORM для Flask. Чтобы установить его, выполните следующие действия:
$ (venv) pip install Flask-SQLAlchemy
Затем замените содержимое файла app.py на следующее:
# app.py
from datetime import datetime
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
app = Flask(__name__)
app.config['SECRET_KEY'] = '5b3ef5s80gl3b217c20fb37044fe4k33'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///default.db"
db.init_app(app)
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), nullable=False)
description = db.Column(db.String(256), nullable=False)
is_done = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.now(), nullable=True)
updated_at = db.Column(db.DateTime, default=None, nullable=True)
def as_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
def __repr__(self):
return f'<Task {self.title}>'
@app.route('/')
def index_view():
return {
'name': 'flask-todo',
'description': 'a simple todo app written in flask',
'version': 1,
}
Этот код настраивает Flask и определяет новую модель под названием Task
. Модель задачи имеет имя
, описание
, is_done
и некоторые другие переменные, такие как created_at
и updated_at
, которые мы будем обновлять динамически.
Далее создайте скрипт Python с именем init_db.py, который инициализирует и заполняет базу данных SQLite:
# init_db.py
from app import db, app
from app import Task
with app.app_context():
db.create_all()
if Task.query.count() == 0:
tasks = [
Task(name='Backup the database', description='Make sure to backup the database with all the tables.'),
Task(name='Setup 2FA', description='Setup the two factor authentication to secure your account.'),
Task(name='Malware scan', description='Perform a malware scan.'),
]
for task in tasks:
db.session.add(task)
db.session.commit()
Запустите сценарий из командной строки:
$ (venv) python init_db.py
Вы заметите, что была создана новая директория с именем instance. В этом каталоге будет находиться файл default.db, который является базой данных по умолчанию.
API
Приложение Flask будет иметь следующие URL-адреса:
/api/
возвращает список всех задач/api/
/ отображает или удаляет конкретную задачу/api/create/
создает новую задачу/api/toggle/
/ переключает свойствоis_done
конкретной задачи
Чтобы реализовать их, добавьте в конец файла app.py следующее:
# app.py
@app.route('/api/')
def list_view():
json = [task.as_dict() for task in Task.query.all()]
return jsonify(json)
@app.route('/api/<int:task_id>/', methods=['GET', 'DELETE'])
def detail_view(task_id):
task = db.get_or_404(Task, task_id)
if request.method == 'DELETE':
db.session.delete(task)
db.session.commit()
return {
'detail': 'Task has been successfully deleted.'
}
else:
return task.as_dict()
@app.route('/api/create/', methods=['POST'])
def create_view():
name = request.form.get('name')
description = request.form.get('name')
if name is None or description is None:
return {
'detail': 'Please provide the name and the description.'
}, 400
task = Task(name=name, description=description)
db.session.add(task)
db.session.commit()
return task.as_dict()
@app.route('/api/toggle/<int:task_id>/')
def toggle_view(task_id):
task = db.get_or_404(Task, task_id)
if task.is_done:
task.is_done = False
else:
task.is_done = True
task.updated_at = datetime.now()
db.session.commit()
return task.as_dict()
Этот код не требует пояснений. Мы определили необходимые маршруты и реализовали необходимую логику. Каждый раз, когда мы хотим внести изменения в базу данных, мы должны зафиксировать()
их.
Вот и все для приложения Flask. В следующих разделах мы подготовим наш проект к развертыванию.
Gunicorn
Веб-сервер Flask не рекомендуется использовать в производстве, так как он рассчитан на обработку одного запроса за раз и может не справиться с большим объемом трафика. Поэтому давайте заменим его на Gunicorn – готовый к производству WSGI-сервер на Python.
Сначала установите его с помощью программы pip:
$ (venv) pip install gunicorn==20.1.0
После успешной установки вы можете запустить сервер следующим образом:
$ (venv) gunicorn -w 2 -b 0.0.0.0:5000 app:app
[INFO] Starting gunicorn 20.1.0
[INFO] Listening at: http://0.0.0.0:5000 (1)
[INFO] Using worker: sync
[INFO] Booting worker with pid: 3
[INFO] Booting worker with pid: 4
Имейте в виду, что эта команда работает только в операционных системах на базе UNIX.
Это запустит два рабочих Gunicorn и откроет ваше приложение на порту 5000
. Чтобы получить доступ к своему приложению, откройте любимый веб-браузер и перейдите по адресу http://localhost:5000.
требования.txt
Последнее, что нам нужно сделать перед докеризацией нашего приложения, – это создать файл requirements.txt. Файл requirements.txt используется для указания зависимостей проекта.
Сгенерируйте его, выполнив следующую команду:
$ (venv) pip freeze > requirements.txt
Другие пользователи (включая контейнеры Docker) могут использовать файл requirements.txt следующим образом:
$ (venv) pip install -r requirements.txt
Приложение Dockerize
Для докеризации приложения мы будем использовать Dockerfile. Dockerфайлы используются для определения инструкций по сборке образов Docker. Они позволяют задать базовый образ, рабочий каталог, переменные окружения, выполнить команды и многое другое.
.dockerignore
Прежде чем работать с Dockerfile, давайте создадим файл .dockerignore. Файл .dockerignore используется для указания папок и файлов, которые должны быть исключены из образа.
.git/
.idea/
instance/
__pycache__/
Обязательно измените файл .dockerignore в соответствии с вашими потребностями.
Dockerfile
Создайте в корне проекта новый файл с именем Dockerfile и следующим содержимым:
# syntax=docker/dockerfile:1.4
FROM --platform=$BUILDPLATFORM python:3.10-alpine
WORKDIR /app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install the requirements
COPY requirements.txt /app
RUN --mount=type=cache,target=/root/.cache/pip \
pip3 install -r requirements.txt
COPY . .
# initialize the database (create DB, tables, populate)
RUN python init_db.py
EXPOSE 5000/tcp
CMD ["gunicorn", "-w", "2", "-b", "0.0.0.0:5000", "app:app"]
Этот Dockerfile использует python:3.10-alpine
в качестве базового образа. Затем он задает рабочую директорию, устанавливает требования, копирует проект, инициализирует базу данных и, наконец, запускает сервер Gunicorn на порту 5000
.
Чтобы узнать больше о Dockerfiles, ознакомьтесь сосправочником Dockerfile .
Тест
Чтобы убедиться, что Dockerfile работает, мы можем собрать и запустить его локально. Чтобы собрать образ, выполните команду:
$ docker build -t flask-todo:1.0 .
Если вы перечислите изображения, то увидите новое изображение:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
flask-todo 1.0 7ege66240eb1 3 hours ago 109MB
Наконец, используйте образ для создания нового контейнера Docker:
$ docker run -it -p 5000:5000 flask-todo:1.0
[2023-02-02 20:08:57 +0000] [1] [INFO] Starting gunicorn 20.1.0
[2023-02-02 20:08:57 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
[2023-02-02 20:08:57 +0000] [1] [INFO] Using worker: sync
[2023-02-02 20:08:57 +0000] [7] [INFO] Booting worker with pid: 3
[2023-02-02 20:08:57 +0000] [8] [INFO] Booting worker with pid: 4
Вы можете использовать
-d
для запуска контейнера Docker в отсоединенном режиме. Это означает, что контейнер работает в фоновом режиме вашего терминала и не получает входные данные и не отображает выходные.
Отлично, теперь ваше приложение работает в контейнере. Перейдите на сайт http://localhost:5000 в вашем любимом веб-браузере, чтобы увидеть ваше веб-приложение в действии.
{
"name": "flask-todo",
"description": "a simple todo app written in flask",
"version": 1
}
Отправить на GitHub
Следующие шаги потребуют от вас наличия учетной записи GitHub. Если у вас его еще нет, зарегистрируйтесь или войдите в систему. Кроме того, убедитесь, что у вас установлен и настроен Git.
После входа в GitHub воспользуйтесь кнопкой “плюс” в правом верхнем углу экрана, чтобы открыть выпадающий список. Далее выберите “Новый репозиторий”:
Выберите пользовательское имя для вашего репозитория. Я выбрал “flask-todo”, затем нажмите “Создать репозиторий”:
После создания репозитория обратите внимание на удаленный URL:
Теперь давайте вернемся в наш локальный проект и перенесем код.
Поскольку у нас есть некоторые файлы, которые мы не хотим отправлять в Git, создайте файл .gitignore в корне проекта. Я добавлю в него следующее, но не стесняйтесь изменять его в соответствии с вашими потребностями:
instance/*
!instance/.gitignore
.webassets-cache
.env
__pycache__/
*.py[cod]
*$py.class
Затем откройте командную строку и выполните следующие команды:
$ git init
$ git remote add origin <your_remote_url>
$ git add .
$ git commit -m "init"
$ git push origin master
Это инициализирует новый Git-репозиторий, добавит удаленное происхождение, VCS всех файлов и создаст начальный коммит. И наконец, выложит исходный код в репозиторий GitHub.
Отлично, теперь все должно быть готово. Если вы теперь перейдете к вашему репозиторию в браузере, вы увидите, что все файлы были зафиксированы.
Развернуть приложение
Следующие шаги потребуют от вас наличия учетной записи Back4app. Если он у вас уже есть, войдите в него, в противном случае зарегистрируйтесь в бесплатном аккаунте.
После входа в систему вы будете перенаправлены на приборную панель вашего приложения. Нажмите на кнопку “Создать новое приложение”, чтобы начать процесс создания приложения.
Back4app позволяет создавать и развертывать два типа приложений: “Бэкенд как сервис” (BaaS) и “Контейнеры как сервис” (CaaS). Поскольку мы хотим развернуть докеризованное приложение, мы будем использовать “Контейнер как сервис”.
Далее подключите свой GitHub к учетной записи Back4app. Обязательно дайте Back4app права на репозиторий, который мы создали в предыдущем шаге. Затем нажмите на зеленую кнопку “Выбрать”, чтобы выбрать его.
Back4app Containers позволяет настроить процесс развертывания. Вы можете задать ветку по умолчанию, корневой каталог, включить/выключить авторазвертывание и задать переменные окружения. Нам ничего из этого не нужно, поэтому просто назовем наше приложение и нажмем кнопку “Создать приложение”.
Back4app потребуется несколько минут, чтобы создать контейнер, загрузить его в реестр контейнеров и запустить. Как только контейнер будет готов, его статус изменится на “Готов”, и вы сможете увидеть зеленый URL в левой части экрана.
Щелкнув по URL-адресу, вы откроете веб-приложение в браузере. Вы заметите, что Back4app автоматически выдал SSL-сертификат для вашего приложения и позволил вам бесплатно разместить приложение Python.
Заключение
В этой статье вы узнали о Python, его преимуществах, недостатках и вариантах развертывания. Вы также успешно развернули простой RESTful API на Python. Теперь вы должны уметь создавать свои простые API и разворачивать их в контейнерах Back4app.
Окончательный вариант исходного кода можно найти на GitHub.
Будущие шаги
- В настоящее время все данные очищаются при каждом переразвертывании. Это происходит потому, что база данных включена в образ Docker. Рассмотрите возможность перехода на управляемый экземпляр базы данных.
- Рассмотрите возможность многоэтапной сборки, чтобы ускорить процесс развертывания.