自分が使っているPython開発環境を晒す(2.Web開発編)
前回の続きです。 今回は予告通り、pythonのWeb開発で使っているものの説明です。 pythonでもweb開発のライブラリ・フレームワークが豊富でユーザー数も多いです。 pythonで機械学習ライブラリが増えてきた結果、webアプリと機械学習は親和性が高いものとなりました(多分)。 機械学習を使ったwebサービス作りたい方に参考なれば幸いです。
今回は特に用語やコード設計について盛り込んでおり、初心者向けではないのでご了承ください。 特にわからないところは、見出しの単語をぐぐって初心者向けの記事を読んだ方がいいかと(小声)
目次
- 自分が使っているPython開発環境を晒す(1.開発環境編)
- 自分が使っているPython開発環境を晒す(2.Web開発編)(この記事)
- 自分が使っているPython開発環境を晒す(3.データサイエンス編前編)
- 自分が使っているPython開発環境を晒す(3.データサイエンス編後編)
Django
pythonでは一番有名なウェブアプリケーションフレームワークでしょうかね。
主な特徴としては
- サーバーアプリの基本であるMVCを使って開発できる
- MVCに従ったアプリの基本構造を自動生成する
- DBのテーブル管理をdjango側がやってくれる
- Ruby on Railsと比べるとルールに従う必要が少ない分、コード量が増えたり技量が必要となる
といった、Railsほどではなくても優しく、大規模Webアプリ向けとなっています。
djangoをpipでインストールすると扱えるCLIでプロジェクトディレクトリを作成できます。
また、作成したプロジェクトディレクトリ直下にあるmanage.py
というスクリプトでWebアプリの開発・管理ができます。
公式チュートリアルを見ればわかりますが、
モデル用、ビュー用、ルーティング用のpythonファイルが作られ、サーバーアプリ開発入門者にも雰囲気が掴めるようになっています。
...とは言っても、
- 実質、テンプレートがビュー、view.pyがコントローラになっていて、名前がややこしい
- モデル(model.py)やコントローラ(view.py)を単一ファイルになっている
といったRailsよりも汚くなったり、実装をするのが難し買ったりします。
反面Railsとは異なり処理が隠蔽されていないので、import文で簡単にオレオレ構造が作れます。 上記を対処すると
- model.pyをモデルごとにコードを分割して、
model
ディレクトリにまとめる view.py
の名前をcontroller.py
にする
ぐらいでしょうか。また、書き方のコツとして、
- コントローラはモデルのデータを(加工して)ビューに渡すだけ
- モデルを太らせる(モデルを重点に機能を実装する)
といったところでしょうか。 今はReduxや クリーンアーキテクチャ の登場によって、サーバー側は自然と上記の書き方をせざるえなくなりましたが、 登場前はMVCの考え方(捉え方を間違っていないか) の議論がされていました。今の時代でも、MVCについて正しい理解をし、コントローラの役割を意識してモデルを太らせることを意識すれば、自然と構造的かつ綺麗にかけます。
Django REST framework
DjangoでAPIを書く場合に重宝します。以下の記事を読むと雰囲気が掴めると思います。
上記の記事では
を解説していますね。特に、モデルの読み書きをJSON形式のREST APIにするだけならこれだけで簡単かつ綺麗に組めます。
リクエスト・レスポンスの定義やコントローラの処理を細かく描きたい場合にも、APIView
やResponse
といったAPIも提供されています。
英語ですが、公式のチュートリアルをざっと読むだけでもしたい処理が簡単にできるようになるのではないでしょうか。
最近は、ビューの処理をフロントエンドで完結できるようになり、
自分もフロントエンドのルーティング以外はこれを使ったAPIしか書いていません。
Djangoを使う際はこれと合わせて使っています。
また、Django REST framework JWT という REST API にJWT認証機能をつけることができるライブラリもあります。 リリースするときを考えて、一緒に使いたいですね。
Flask
小・中規模のサーバーフレームワークです。自分はプロトタイピングによく使っています。 ほぼ公式のコードですが、以下の数行ですぐにサーバーアプリが作れます。
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!' if __name__ == '__main__': app.run()
上記をapp.py
というファイル名で保存すれば、python main.py
コマンドを実行して http://localhost:5000 で起動できます。
上記のようにデコレータにパスやメソッドを指定し、返り値にAPIやhtmlの出力を返してやるだけでサーバーアプリが書けます。 flask標準でテンプレートのレンダリングやjsonのアウトプットのラッパー関数がある他、ステータスコードやヘッダを自分で設定できたりもします。 ただし、flaskにはデータベースの操作・管理機能はないので、使いたい場合にはSQLAlchemyなどのライブラリを使いましょう。
また、viewの関数のコードをファイルに分割することができ、flaskでもMVCベースのアプリが書けます。 下記のSQLAlchemyを使えば、多少規模が大きいアプリでも問題なく扱えることができます。
参考:Flaskで大きいアプリケーションを作るときのTips
他にもbottleやtornadoなど他にも小規模webライブラリはありますが、自分はflaskでほぼ不便なくコーディングできて、主にこれを扱っています。 ユーザー数も多い方らしく、追加機能となるライブラリも豊富です。
Flask-RESTful
FlaskでREST APIを書く場合に重宝します。標準でもJSONのAPIは書けますが
といったアプリの保守性に優れたコードを書くことができます。
また、FlaskのBlueprintを使わずともFlask-RESTfulのAPI定義をファイルごとに分割できますが、 Blueprintを使った構築も公式でサポートされています。フロントエンドもFlaskでパス通す場合はBlueprint使った方がいいです。
SQLAlchemy
pythonでRDBを扱うときに便利なDBライブラリです。 基本的な機能としては
といったDjangoのRDB操作と似たような機能を持っています。前述の通りFlaskのような小規模サーバーライブラリは標準でRDBの操作機能を持っていませんので、
SQLAlchemyなどに頼ることになります。メソッドチェーンの容量でSQLの処理を書き連ねることができ、
最後にデータ呼び出しはall
メソッド、データ書き込みはcommit
メソッドで実行することができます。
具体的な使い方は他の記事に任せますが、テーブルごとにソースファイルを分けるのが難しいです。 個人的には分けて使いたかったので、以下のstackoverflowに上っていた対処法を参考にテーブルの定義を分割しています。
python - SQLAlchemy classes across files - Stack Overflow
自分はFlaskでデータベースを使いたいときに使っています。
jinja2
DjangoやFlaskで扱われているテンプレートエンジンです。
ただし、上記のようにREST APIを出力するだけのサーバーアプリを書く場合には全く必要ないです。 実際に私もこれに頼ることはほとんどなく、フロントエンドにおいてVue.jsでのプロトタイピングの際に文法が競合してむしろ迷惑になります。
Vue.jsを使う場合はこれを参考にjinja2の文法を変えています。
pipを使わずとも大抵Djangoやflaskについています。
uWSGI
pythonサーバーアプリのデプロイをする際に用います。 早い話、こいつがサーバーアプリの面倒をみる役割を持っています。 こいつを使う際は、uWSGIの設定ファイルを用意して使い(必須ではないが使った方がいい)、 アプリのパスやプロセスIDファイル、ログファイルを設定することになります。 ちなみに私はuWSGIとnginxを組み合わせて使っていますが、最近はサーバーレスな構築できるようになりuWSGIだけで十分なケースも現れました。 EC2にuWSGIとnginxを載せた時は結構大変でしたので、サーバーレスでuWSGIだけを使うのが良いと思います。
API Blueprint
APIの仕様書を書くのに特化したマークアップ言語です。 基本はMarkDown準拠でAPIパスに対し、メソッドごとに仕様の説明やパラメータ、リクエスト・レスポンスのJSONスキーマの定義などをこれで書きます。
共同開発には必須となるでしょう。
また、apiaryというサービスを使えば、ウェブ上でAPI Blueprint準拠のドキュメントが書け、これをベースにAPIのモックが書けます。
社内のアプリ開発に関しては、少人数のスタートアップなので、基本自分だけで開発していました。 そのため、ほとんど使う機会はありませんでしたが、そろそろ共同開発することも増えてきて導入を検討しています。