Рубрики
Без рубрики

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

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

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

Введение

Sanic Это очень похожий на флянку веб-сервер Python Python и веб-структуру с более чем 10K звезд Это написано, чтобы идти быстро. Это позволяет использовать Асинхрон/жду Синтаксис добавлен в Python 3.5 (читать далее) , что делает ваш код не блокировка и быстрым.

Sanic имеет довольно хорошее Документация И это поддерживается сообществом для сообщества.

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

Требования

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

Примечание: исходный код доступен в моем github.com репозиторий. Для каждого шага есть соответствующий коммит.

Предварительные условия:

  • Python3.6+
  • пипенв (Вы можете использовать любой другой установщик пакета)
  • Postgresql (Для базы данных также может быть MySQL или SQLite)

Пакеты:

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

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

  • SANIC-ENVCONFIG это расширение, которое помогает вам внести командную строку и переменные среды в саническую конфигурацию.

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

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

Pipenv-Python Python3.6

Установите все необходимые пакеты с помощью Pipenv команды ниже.

Pipenv Установите Sanic Secure Environs Sanic-envconfig

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

Pipenv установить базы данных [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 Файл, чтобы сделать папку проекта доступной в качестве пакета в нашем коде.

from setuptools import setup

setup(
    name='project',
)

Установка…

Pipenv Установка -e.

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

__main__.py создан для выполнения исполняемого пакета проекта из командной строки.

Pipenv Run Python -M Project

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

Давайте сделаем наш первый звонок в __main__.py файл.

from project.main import init

init()

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

from sanic import Sanic

app = Sanic(__name__)

def init():
    app.run(host='0.0.0.0', port=8000, debug=True)

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

Бег…

Pipenv Run Python -M Project

Если вы откроете http://0.0.0.0:8000 В вашем браузере вы увидите

Ошибка: запрошенный URL/не найден

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

Настройки

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

.env файл.

DEBUG=True
HOST=0.0.0.0
POST=8000

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

from sanic import Sanic

from environs import Env

from project.settings import Settings

app = 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,    
    )

настройки.py файл.

from sanic_envconfig import EnvConfig

class Settings(EnvConfig):
    DEBUG: bool = True
    HOST: str = '0.0.0.0'
    PORT: int = 8000

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

База данных

Теперь пришло время настроить базу данных.

Одна маленькая заметка о пакете баз данных, прежде чем мы продолжим:

Базы данных Пакет использует Asyncpg которая является асинхронной библиотекой интерфейса для PostgreSQL. Это довольно быстро. См. Результаты ниже.

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

After_server_start After_server_stop

main.py файл.

from sanic import Sanic

from databases import Database # <- this line

from environs import Env
from project.settings import Settings

app = Sanic(__name__)

def setup_database(): # <- this function
    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() # <- this line

    app.run(
        host=app.config.HOST, 
        port=app.config.PORT, 
        debug=app.config.DEBUG,
        auto_reload=app.config.DEBUG,    
    )

Еще раз. Нам нужно указать DB_URL В настройках проекта и среде.

.env файл.

DEBUG=True
HOST=0.0.0.0
POST=8000
DB_URL=postgresql://postgres:postgres@localhost/postgres # <- this line

И в настройки.py файл.

from sanic_envconfig import EnvConfig

class Settings(EnvConfig):
    DEBUG: bool = True
    HOST: str = '0.0.0.0'
    PORT: int = 8000
    DB_URL: str = '' # <- this line

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

Столы

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

Давайте объявим таблицу в tables.py Файл с использованием sqlalchemy.

import sqlalchemy


metadata = 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)),
)

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

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

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

# Executing many
query = 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 rows
query = books.select()
rows = await app.db.fetch_all(query)

# Fetch single row
query = books.select()
row = await app.db.fetch_one(query)

Маршруты

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

from sanic.response import json
from project.tables import books

def 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]
        })

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

from project.routes import setup_routes # <- this line

app = Sanic(__name__)

def init():
    ...
    app.config.from_object(Settings)
    setup_database()
    setup_routes(app) # <- this line
    ...

Запрашивая…

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

Средние войны

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

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

Как вы можете видеть, нам нужны некоторые улучшения безопасности. Есть некоторые недостающие заголовки, такие как X-xss-protection , Строго-транспортный-безопасность … Итак, давайте позаботимся о них, используя комбинацию Middlewares и безопасные пакеты.

Middlewares.py файл.

from secure import SecureHeaders

secure_headers = SecureHeaders()

def setup_middlewares(app):
    @app.middleware('response')
    async def set_secure_headers(request, response):
        secure_headers.sanic(response)

Настройка Middlewares в main.py файл.

from project.middlewares import setup_middlewares

app = Sanic(__name__)

def init():
    ...
    app.config.from_object(Settings)
    setup_database()
    setup_routes(app)
    setup_middlewares(app) # <- this line
    ...

Результат:

$ curl -I localhost:8000/books
Connection: keep-alive
Keep-Alive: 5
Strict-Transport-Security: max-age=63072000; includeSubdomains
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer, strict-origin-when-cross-origin
Pragma: no-cache
Expires: 0
Cache-control: no-cache, no-store, must-revalidate, max-age=0
Content-Length: 32
Content-Type: text/plain; charset=utf-8

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

Давитовмаян/Саниский Проект

Спасибо за чтение. Быстро иди с саникой и удачи !!!

Оригинал: “https://dev.to/davitovmasyan/how-to-make-your-code-fast-and-asynchronous-with-python-and-sanic-1947”