sasau’s diary

作ったもので2年に一回くらいの更新を目指す

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)

作ったもの

こちらになります。

github.com

以下はこれの解説になります。 なお、使っている主な技術を先に列挙すると

  • 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)

apipages入れ子にしています。

/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')

hellotodo入れ子にしていて、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は難しい印象を受ける方も多いと思いますし、実際慣れるまでは挙動の想像がしづらかったりするのですが ちゃんと書けば性能として帰ってくるし気分も良いので、これから挑戦してみようという方の一助になればと思います。

ワイWebエンジニア、なんJのためになんかしたい

自分は色々あって野球chからなんJに入植したなんJ民の第一世代だ。最近はなんJというコミュニティ(?)に対してエンジニアとして何か貢献したいという気持ちが強くなっていて、こういうスレを建てたりしていた。

ワイWebエンジニア、なんJのためになんかしたい | ログ速@2ちゃんねる(sc)

いち住民として、近年は全盛期と思えるくらいに居心地の良い場所になっているなと感じていて、なんJは雑談のためのUI/UXという意味でかなり理想的なものになっているように思う。
個人的には

  • スレの保持数が少ないため、盛り上がっているスレがすぐにわかり、そうでないスレは落ちる
  • そもそも雑談なんて長いスパンで行われるものではない
  • 野球という薄いコンテキストがあると雑談が成立しやすい
  • 野球というテーマによって定期的に話題の流入があるため淀みにくい

が良い点かなと思う。*1

ただ、「現在そうなっていること」にはそれなりの歴史的経緯があるため、他の場所での再現性があるわけではないのだけど。 自分もプログラミングに関する質問があったらできる範囲で積極的に答えるようにしている。teratailやstackoverflowで活動している人にとっては、回答が自分に帰属しないような場所でそれをするのは不思議に感じるかもしれない。


近年はインターネットで何者かになりたい・ならなければという話題は誰もが興味を引く「エモい」話題で、自分もそういう欲求があるから誰も使わないアプリ作ったりしている。

けれども、ここで言われているような強者にはなれないなと思うし、そういう人の方が多いだろうと思う。
強者である人は、社会的な強さだったり、文章のうまさだったり、何らかの生きづらさだったり、専門性の高さだったり、ゲームの上手さだったり、毎日ブログや動画を投稿できるマメさだったりがあるわけだけど
それ以前の問題として自分は人に見せられるような、コンテンツにはなれないなと感じる。
なのでまあ、今日も明日も集合的無意識の一部に溶け込んで生きるのだと思う。ずっと前からそうだったのでおっさん的な諦観と言われると辛いものがあるが...。


建てたスレはそれほど伸びずに25で落ちたけれども、何かできることは探していこうと思う。
スレの書き込み的には最近はWindowsのPC向けの専用ブラウザの不満が高まっているのを感じる。個人的にはkakikomi.txtをウェブで一元管理などができると良いなと思っているのでその辺りを組み込んだやつが作れるといいかなと思う。ただ、現在は専用ブラウザの開発が制限されているのでなかなか難しい....。

Tevereのデータを多少更新した

https://tevere.ccで集めているデータはhttp://dbpedia.org/sparql で集めているが
http://wikidata.dbpedia.org/sparqlのデータを集めて年月日に関するデータはこっちの情報を優先して正とする。
というような修正をした。
それによって、いくつかの日付情報が修正され、真珠湾攻撃などいくつか表示されていなかった戦いが表示されるようになった。

続きを読む

歴史上の戦いを年代ごとにGoogle Mapにプロットして指揮官やカテゴリで絞り込んで見られるやつ

を作った。

http://tevere.cc

f:id:ssuwam:20180529145522p:plain

データは例によってDBpediaから集めている。

何ができるの?

スライダーを動かすと表示する戦いの年代を選ぶことができる。
地図上に表示されたマーカーが戦いが行われた場所を示し、マーカーをタップすると詳細が表示される。

詳細にはその戦いで指揮した司令官、その戦いが含まれるカテゴリが表示されて
それをタップするとその司令官が参加した戦いやそのカテゴリの戦いを絞り込むことができる。 f:id:ssuwam:20180529145855p:plain

続きを読む

Tap strapのモード切り替え時のチートシート

未来を感じるキーボード「Tap」を触ってみた - 生涯未熟

この方の記事を見て、片手入力デバイスに興味があったので購入した。
この記事も(半ば意地になりつつも)例によってそれで書いている。

このキーボードはブラスナックルのような形状をしていて、机を叩いた時の指の振動を使ってタイピングする。
片手で使う場合5本の指の組み合わせで31通りになるので
アルファベットの他の記号や数字などはn回タップするとか中指薬指小指タップでモードを切り替えたりしてタイプするということになっている。
で、モードを切り替えた時のチートシートが見当たらなかったので試した結果を置いておく。
日本語を使う我々には割と重要な気がする…。
おそらくOSに依存する部分があるので注意。以下の結果はMac OSで試した。

続きを読む

gitコマンドと自分メモ

はじめに

自分がgitで使っているコマンドを列挙している。
もう2,3年これより増えても減ってもいないし増やすモチベーションもない。
自分がgitを使いこなせているのか...みたいな話は人それぞれだと思うし僕も自信はないんだけどgitはそこまで使いこなせなくてもいい道具の一つだとも思う。
なのでまあ、一人のしょぼいエンジニアはgitをただ使うにあたってこのくらいの知識で終わっているということ。
2018年に書くようなことでもないんだけど...2年くらい前の書きかけのQiita teamの下書きに埋もれてたのでこっそりと。

続きを読む

fastTextのベクトルの類似検索でYAHOOのNGTを使う。

fasttextにWikipedia全文を食べさせて遊んでいた(だいたい以下の記事の内容)。

qiita.com

「パリ - フランス + 日本」とかそういうやつ(だいたい以下の記事の内容)。

antibayesian.hateblo.jp

続きを読む