Cara membuat kode Python Anda cepat dan tidak sinkron dengan Sanic

Untuk mengantisipasi dimulainya kursus " Pengembang Python. Profesional ", kami telah menyiapkan terjemahan tradisional dari artikel yang bermanfaat.


Halo semuanya, dalam artikel ini saya akan berbicara tentang membuat proyek asinkron sederhana pada kerangka kerja Sanic.

pengantar

Sanic – Flask - - Python 10 , . async/await, Python 3.5, .

Sanic , .

– HTTP-, , .

, , , .

: github. . 

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 setup

setup(
    name='project',
)

…

pipenv install -e .

.env , . 

_main_.py , project .

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)

app Sanic, , , debug.

…

pipenv run python -m project
Keluaran konsol Sanic
Sanic console output

Sanic . http://0.0.0.0:8000, :

Error: Requested URL / not found

, . .

. .env, Sanic.

.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,    
    )

settings.py

from sanic_envconfig import EnvConfig


class 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 Sanic
from databases import Database
from environs import Env
from project.settings import Settings
app = 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=True
HOST=0.0.0.0
POST=8000
DB_URL=postgresql://postgres:postgres@localhost/postgres

settings.py:

from sanic_envconfig import EnvConfig


class 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 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)),
)

, books . Alembic – , 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 books.

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

, , init setup_routes.

from project.routes import setup_routes
app = 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:8000
Connection: keep-alive
Keep-Alive: 5
Content-Length: 32
Content-Type: text/plain; charset=utf-8

, . , X-XSS-Protection, Strict-Transport-Security .. secure.

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)

middleware 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)
    ...

:

$ 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

, github. , Sanic. Sanic , .


. " Python C: Python " .




All Articles