Pythonプロジェクトのディレクトリ構成

Posted by rhoboro on 2018-01-25

--- 2018/01/30 追記[ここから] ---

pip の constraints の正しい用途@methaneさんより「Constraints(pipの-cオプション)を使わずに、-rオプションだけで十分」との指摘をいただいたのでリポジトリを更新しています。
また、上記に伴い、リポジトリ上ではmake constraintsを削除し、make lockfilemake update-dependenciesを追加しました。
こちらのQiitaの記事はとても良い記事ですので、コメント欄まで含めてご確認いただければと思います。

--- 2018/01/30 追記[ここまで] ---

--- 2021/01/16 追記[ここから] ---

最近は下記のテンプレートを利用しています。

基本的な方針はこの記事と同じですが、mypy、black、isortを追加し、それぞれの設定ファイルも含めています。 概要は下記のようになっています。

  • 1行あたり100文字まで
  • isortとblackが競合しない設定
  • pytestとmypyをすぐ使い始められるような設定

--- 2021/01/16 追記[ここまで] ---

こちらのツイートの通り、同僚の@canoefishingがいま開発中のプロジェクトのディレクトリ構成を褒めてくれたのでスケルトンコードにして晒してみます。 少しでも誰かの参考になれば幸いです。 何かを参考にしたわけでなく、わたし自身の経験に基づいたものなのでもっといい方法があれば教えてください。

fish_comment

前提

いま開発中のコードが元になっているため、下記のようなWebアプリを想定しています。 ただし、srcの中身以外は少し変えるだけで汎用的に使えると思います。

  • PythonのFlaskで構築するWebアプリ
    • 設定切り替えはFlaskに依存
  • 主にAPIサーバーを想定
    • Blueprintsを使っているので多少のUI開発くらいならいける
  • constraints.txtを利用
    • 利用したいライブラリとその依存ライブラリを明確に区別しておきたいのでconstraints.txtを利用
  • Dockerを利用
    • わたし個人ではDockerを使わないプロジェクトはもうほぼない

プロジェクト構成

百聞は一見にしかず。
スケルトンコードはrhoboro/webapp_skeletonに置いています。
さっそくgit clone [email protected]:rhoboro/webapp_skeleton.gitをしてみてください。 cloneできたら、 make test を実行してみましょう。 テストが動くはずです。
その他のコマンドに関してはすべてREADME.mdに書いてあります。

後から用意するのは大変だと経験上学んでいるので環境ごとの設定ファイル切り替え、テスト実行環境、CIの設定ファイル、Dockerfile、Makefileあたりを最初に用意するんだけどそれ見た @canoefishing が褒めてくれたので今日はハッピーだった

上記ツイートより。

それではプロジェクト構成の概要を説明へ。

構成の概要

  • Makefile

    • 都度docker ...と打つのが面倒なのでショートカットとして用意
    • 用意しているコマンドは4つ
      • dev: 開発用設定で起動
      • production: 本番用設定で起動
      • constraints: constraints.txtを出力
      • test: テストはpytestを利用し、Linterはflake8を利用
    • すべてはDockerコンテナ上で実行
      • 本番でも同じように利用したいのでソースコードはマウントでなくCOPY
  • 環境ごとの設定ファイル切り替え

  • ライブラリの依存関係管理

  • テスト実行環境

    • テスト環境はあとから追加しようと思うと超大変。最初に用意するのが大切
    • unittestをベースにし、src/tests/に格納
      • 標準に合わせておくほうが何かと楽
    • 通信を行うテストが増え重くなってきたのでpytestを導入した
  • CIの設定ファイル

    • CI環境もあとから追加しようと思うとちょっと大変。最初に用意するのが大切
    • うちは大体どのプロジェクトもCircle CIを利用しています
    • 今回のスケルトンコードはまだデプロイの必要がないためテストのみ
      • わたしが関わっているプロジェクトはほぼ全てmasterへのマージで自動デプロイされるようにしています
      • 開発はdevelopブランチで行い、stagingブランチへのマージでステージング環境に自動デプロイ
  • Dockerfile

    • Dockerfileの書き方に慣れておくのが大事
      • (プロジェクト開始直後の簡単なWebアプリ環境なら)慣れてたらすぐ書ける
    • 開発時から利用しておくと吉
      • 本番でもできるだけGKE(k8s)を使いコンテナで
      • GCEやEC2でもDockerで動かせるようにしておくとデプロイが段違いで楽になる
      • 開発時にDBが必要になったらdocker-compose
    • 他の人にも触ってもらいやすくなる
      • 自分以外にテストや動作確認をしてもらうために都度環境構築を頑張ってもらうのは酷
  • その他普段から気をつけている点

    • README.mdを必ず書く
    • ソースコードは一段下げ、プロジェクトのトップディレクトリには置かない
      • Dockerfileでまるっとディレクトリを指定したい
    • ドキュメントをしっかりと残す
      • GitHubのwikiに集約
      • 明日の自分は他人
      • 自分自身を含めプロジェクトメンバーはいつ変わるかわからない
      • 環境構築系の質問はとても時間を食う。双方にとって時間の無駄でしかない
    • いつPCが壊れてもいいようにしておく
      • *rc系のファイルも自分のリポジトリにコミットしておく
      • ここまでのことができていればいつ開発用PCが壊れても怖くない
      • OSのメジャーアップデートはクリーンインストールで練習台にする笑

いけてない点

  • ホスト上では依存関係の解決ができないので警告が出る

  • デプロイ系のスクリプトが出てきたらどうするか問題

    • デプロイスクリプトはアプリと一緒に管理したい
      • masterへのコミットで自動デプロイしたいため
    • GKEの利用等でアプリと同階層でNginxイメージを用意する場合などはソースをさらに1段下げる必要がありそう

まとめ

下記を必ず用意しましょう。早ければ早いほど導入は楽になります

  • テスト環境
  • CI環境
  • Dockerfile
  • 自分の設定ファイル(*rc系等)を格納しておくリポジトリ

tags: python