Русский
Русский
English
Статистика
Реклама

Перевод Как сделать ваш код на Python быстрым и асинхронным с Sanic

В преддверии старта курса "Python Developer. Professional" подготовили традиционный перевод полезной статьи.


Всем привет, в этой статье я расскажу о создании простых асинхронных проектов на фреймворке Sanic.

Введение

Sanic это очень похожий на Flask открытый веб-сервер и веб-фреймворк на Python с более чем 10К звездами, который быстро развивается. Он позволяет использовать синтаксис async/await, который был добавлен в Python 3.5, помогая делать ваш код неблокирующим и быстрым.

У Sanic очень хорошая документация, которая пишется членами сообщества для самого сообщества.

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

Требования

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

Примечание: Исходный код есть на моем github. Каждый шаг отражен в отдельном коммите.

Предустановки

  • Python3.6+

  • pipenv (или любой другой установщик пакетов)

  • PostgreSQL (для баз данных, можно также взять MySQL или SQLite)

Пакеты

  • secure это легкий пакет, который добавляет заголовки безопасности и атрибуты файлов cookie для веб-фреймворков Python.

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

  • sanic-envconfig это расширение, которое помогает вам переносить командную строку и переменные окружения в вашу конфигурацию Sanic.

  • databases это пакет Python, который позволяет создавать запросы с использованием мощного языка выражений SQLAlchemy Core и обеспечивает поддержку PostgreSQL, MySQL и SQLite.

Давайте создадим пустой каталог и инициализируем пустой Pipfile.

pipenv --python python3.6

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

pipenv install sanic secure environs sanic-envconfig

Для базы данных:

pipenv install databases[postgresql]

На выбор postgresql, mysql, sqlite.

Структура

Теперь давайте создадим несколько файлов и папок, где мы будем писать код.

 .env Pipfile Pipfile.lock setup.py project     __init__.py     __main__.py     main.py     middlewares.py     routes.py     settings.py     tables.py

Мы будем использовать файл setup.py, чтобы сделать папку project доступной как пакет в нашем коде.

from setuptools import setupsetup(    name='project',)

Установка

pipenv install -e .

В файле .env мы будем хранить глобальные переменные, такие как строку подключения к базе данных.

_main_.py создан для того, чтобы наш пакет project мог выполняться из командной строки.

pipenv run python -m project

Инициализация

Давайте сделаем первый вызов в файле main.py

from project.main import initinit()

Это начало нашего приложения. Теперь нам нужно создать функцию init в файле main.py.

from sanic import Sanicapp = Sanic(__name__)def init():    app.run(host='0.0.0.0', port=8000, debug=True)

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

Запускаем

pipenv run python -m project
Sanic console outputSanic console output

При успешном запуске приложения Sanic вывод будет выглядеть именно так. Если в браузере вы откроете http://0.0.0.0:8000, то увидите:

Error: Requested URL / not found

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

Настройка

Теперь мы можем модифицировать среду и настройки. Нам нужно добавить некоторые переменные в файл .env, прочитать их и передать в файл конфигурации приложения Sanic.

Файл .env

DEBUG=TrueHOST=0.0.0.0POST=8000

Конфигурация

from sanic import Sanicfrom environs import Envfrom project.settings import Settingsapp = Sanic(__name__)def init():    env = Env()    env.read_env()        app.config.from_object(Settings)    app.run(        host=app.config.HOST,         port=app.config.PORT,         debug=app.config.DEBUG,        auto_reload=app.config.DEBUG,        )

Файл settings.py

from sanic_envconfig import EnvConfigclass Settings(EnvConfig):    DEBUG: bool = True    HOST: str = '0.0.0.0'    PORT: int = 8000

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

База данных

Сейчас самое время настроить базу данных.

Одно замечание о базе данных прежде, чем мы пойдем дальше.

Пакет databases использует asyncpg, который является асинхронным интерфейсом библиотеки для работы с PostgreSQL. Работает достаточно быстро. Результаты вы можете посмотреть ниже.

Мы будем использовать двух слушателей Sanic, для которых укажем операции подключения и отключения от базы данных. Вот слушатели, которых мы будем использовать:

  • afterserverstart

  • afterserverstop

Файл main.py

from sanic import Sanicfrom databases import Databasefrom environs import Envfrom project.settings import Settingsapp = Sanic(__name__)def setup_database():    app.db = Database(app.config.DB_URL)    @app.listener('after_server_start')    async def connect_to_db(*args, **kwargs):        await app.db.connect()    @app.listener('after_server_stop')    async def disconnect_from_db(*args, **kwargs):        await app.db.disconnect()def init():    env = Env()    env.read_env()        app.config.from_object(Settings)    setup_database()    app.run(        host=app.config.HOST,         port=app.config.PORT,         debug=app.config.DEBUG,        auto_reload=app.config.DEBUG,        )

И еще кое-что. Нам нужно указать DB_URL в настройках проекта и среде.

Файл .env

DEBUG=TrueHOST=0.0.0.0POST=8000DB_URL=postgresql://postgres:postgres@localhost/postgres

И файл settings.py:

from sanic_envconfig import EnvConfigclass Settings(EnvConfig):    DEBUG: bool = True    HOST: str = '0.0.0.0'    PORT: int = 8000    DB_URL: str = ''

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

Таблицы

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

Давайте объявим таблицу в файле tables.py с помощью SQLAlchemy.

import sqlalchemymetadata = sqlalchemy.MetaData()books = sqlalchemy.Table(    'books',    metadata,    sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True),    sqlalchemy.Column('title', sqlalchemy.String(length=100)),    sqlalchemy.Column('author', sqlalchemy.String(length=60)),)

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

Теперь мы можем использовать любые запросы SQLAlchemy. Ниже представлены несколько примеров.

# Executing manyquery = books.insert()values = [    {"title": "No Highway", "author": "Nevil Shute"},    {"title": "The Daffodil", "author": "SkyH. E. Bates"},]await app.db.execute_many(query, values)# Fetching multiple rowsquery = books.select()rows = await app.db.fetch_all(query)# Fetch single rowquery = books.select()row = await app.db.fetch_one(query)

Маршруты

Теперь нам нужно настроить маршруты. Давайте перейдем в routes.py и добавим новый маршрут для books.

from sanic.response import jsonfrom project.tables import booksdef setup_routes(app):    @app.route("/books")    async def book_list(request):        query = books.select()        rows = await request.app.db.fetch_all(query)        return json({            'books': [{row['title']: row['author']} for row in rows]        })

Конечно же, чтобы все работало, нам нужно в init вызвать setup_routes.

from project.routes import setup_routesapp = Sanic(__name__)def init():    ...    app.config.from_object(Settings)    setup_database()    setup_routes(app)    ...

Делаем запрос

$ curl localhost:8000/books{"books":[{"No Highway":"Nevil Shute"},{"The Daffodil":"SkyH. E. Bates"}]}

Middleware

Может проверим заголовки ответов и посмотрим, можем ли мы добавить или исправить там что-нибудь?

$ curl -I localhost:8000Connection: keep-aliveKeep-Alive: 5Content-Length: 32Content-Type: text/plain; charset=utf-8

Как видите, в вопросах безопасности нам есть что улучшить. Есть несколько пропущенных заголовков, таких как X-XSS-Protection, Strict-Transport-Security и т.д. Поэтому давайте разберемся с ними с помощью дополнительного ПО и пакетов secure.

Файл middlewares.py

from secure import SecureHeaderssecure_headers = SecureHeaders()def setup_middlewares(app):    @app.middleware('response')    async def set_secure_headers(request, response):        secure_headers.sanic(response)

Настройка middleware в файле main.py:

from project.middlewares import setup_middlewaresapp = Sanic(__name__)def init():    ...    app.config.from_object(Settings)    setup_database()    setup_routes(app)    setup_middlewares(app)    ...

А вот и результат:

$ curl -I localhost:8000/booksConnection: keep-aliveKeep-Alive: 5Strict-Transport-Security: max-age=63072000; includeSubdomainsX-Frame-Options: SAMEORIGINX-XSS-Protection: 1; mode=blockX-Content-Type-Options: nosniffReferrer-Policy: no-referrer, strict-origin-when-cross-originPragma: no-cacheExpires: 0Cache-control: no-cache, no-store, must-revalidate, max-age=0Content-Length: 32Content-Type: text/plain; charset=utf-8

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


Подробнее о курсе. Посмотреть запись открытого урока "Расширение Python на C: заставляем Python ползти быстрее" можно здесь.

Источник: habr.com
К списку статей
Опубликовано: 23.11.2020 14:22:47
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании otus. онлайн-образование

Python

Программирование

Sanic

Категории

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

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru