Sanic+Ginoの開発環境ボイラープレート
Python Advent Calendar 2018 - Qiitaの12/13の記事です。
Sanicって良いですよね。速いし、シンプルだし、ドキュメントも充分です。
もうすぐ2019年になりますし、Pythonでサーバーを書くならasyncioを使ってノンブロッキングに実装したいものです。
個人的にWebフレームワークはDjangoみたいなフルスタックなものよりFlaskみたいな小さいものから始めて適宜追加していく方が全体を把握しやすいので好きです。
しかしながら、シンプルといってもウェブアプリケーションを作るなら
- 新しいURLルーティングが増えた時に整理しやすいようにしておく
- テストを書きやすいようにしておく
- コンフィグ等を拡充しやすいようにしておく
- DBとの接続やマイグレーションを出来るようにしておく
といったことは治安を守って快適に開発していくためには最低限必要なことかなと個人的には思います。
SanicのHello World Exampleから始めるのではなく、↑が揃ったSanic用のボイラープレートでもあればなあと考えていたので最近作った開発環境を晒したいと思います。
↓Hello World Example
from sanic import Sanic from sanic.response import json app = Sanic() @app.route('/') async def test(request): return json({'hello': 'world'}) if __name__ == '__main__': app.run(host='0.0.0.0', port=8000)
作ったもの
こちらになります。
以下はこれの解説になります。 なお、使っている主な技術を先に列挙すると
- Python3.7
- Docker
- docker-compose
- Pipenv
- Sanic
- tox
- pytest
- Postgre SQL
- Alembic
- Gino
- SQLAlchemy
といった感じです。
とりあえず動かす
https://github.com/sasaujp/sanic-gino-boilerplateをコピーなりcloneなりして
$ docker-compose up -d $ pipenv install --dev $ pipenv run tox
を実行するとdocker-composeでPostgreSQLが立ち上がり、pipenvでパッケージがインストールされ、toxでテストが起動し、一通りのコードが実行されます。 サーバーを起動する場合は最後を
$ pipenv run python main.py
とするとポート8000でサーバーが起動します。
URLルーティング
/myapp/blueprints
を見てください。
/myapp/blueprints/__init__.py
を見ると
from sanic import Blueprint from .api import api from .pages import pages bp = Blueprint.group(api, pages)
api
とpages
を入れ子にしています。
/myapp/blueprints/api/__init__.py
を見ると
from sanic import Blueprint from .hello import hello from .todo import todo api = Blueprint.group(hello, todo, url_prefix='/api')
hello
とtodo
を入れ子にしていて、url_prefix
が設定されています。
/myapp/blueprints/api/hello.py
を見ると
from sanic import Blueprint, response hello = Blueprint('hello_api', url_prefix='/hello') @hello.route('/world') async def hello_api(request): return response.json({'hello': 'world'})
Hello, WorldなAPIがあります。
SanicのBlueprintは入れ子にすることができ、url_prefix
でpathの設計が出来ます。
トップのBlueprintはここで登録されているため、
このAPIは/api/hello/world
でアクセスすることができます。
テスト
toxを使用し、pytestでテスト、flake8, mypyで文法チェックをしています。
よく使われている方法だと思われ、検索で出てくる情報も豊富なので細かく解説はしませんが
tox.ini
で設定をしています。
コンフィグ
myapp/config.py
にあります。
今はまだDBの設定を書いているくらいであまり書くことはないのですが、tox.iniでセットしている環境変数でテスト用のコンフィグに分岐するようにしていて、普段とDB名が変わるようにしています。
/myapp/__init__.py
で登録しています。
DB関連
マイグレーション
マイグレーションとはDBのスキーマの変更をバージョン管理するためのもので、Alembicを使っています。
これもよく使われている技術で情報も豊富なので細かく解説はしません、しませんが
このボイラープレートを開発に使う場合は/alembic/versions
の中身を消した上で始めると良いと思います。
Gino
Ginoは今回使った技術の中でそこまでメジャーではない部類になるのかなと思います。
ノンブロッキングなWebサーバーを実装するにあたってSQLAlchemyとDBを非同期IOで橋渡しをしてくれるものが必要でした。
GinoはPostgre SQLにしか対応していませんが、とても使いやすい印象を受けたので採用しています。
Ginoの初期化は/myapp/blueprints/events.py
でサーバー起動時に行なっています。
具体的な操作は/myapp/blueprints/api/todo.py
のTodo APIで行なっています。
挙動のテストは/tests/http/test_todo.py
で行なっています。
SQLAlchemyを使っている人であればかなり手に馴染むのではないかなと思います。
終わりに
この記事、および今回作ったものは個人開発で出来てない部分の自戒のために書いたのは正直あります。
プライベートでは勢いで書き始めて辛い思いをすることがほとんどなので...。
asyncioや非同期IOは難しい印象を受ける方も多いと思いますし、実際慣れるまでは挙動の想像がしづらかったりするのですが
ちゃんと書けば性能として帰ってくるし気分も良いので、これから挑戦してみようという方の一助になればと思います。