概要
新しいプロジェクトを作るとき、毎回一から環境構築するのは面倒だし、ミスがあるかもしれないし、そんな反復作業をするより開発に時間を回したい!
ということで、Python用のパッケージ管理ツールの一つである「Poetry」を使ったPythonプロジェクトのテンプレートを作ってみた。
自分用ではあるけど、基本的な構成ではあるため他の人も使えるように公開している。
構成はざっと以下の通り。
- poetry (パッケージ管理ツール)
- flake8 (リンター)
- black (フォーマッター)
- pytest (テスト)
- taskipy (タスク定義)
- pyinstaller (実行ファイル化)
- .vscode/settings.jsonでファイル保存時自動フォーマット
本記事で説明すること
- つかいかた
- 内容解説
本記事で説明しないこと
- poetryのインストール手順 (poetryはインストール済であることが前提)
- poetry自体の使い方・解説
- 各ライブラリの詳細な解説
つかいかた
clone
GitHubに公開してるので基本的にcloneしてあとは良しなに。
projectName
は好きなプロジェクト名に置き換えてください。
git clone https://github.com/torippy1024/poetry-template.git projectName
cd projectName
poetry install
ディレクトリ構成
ディレクトリ構成は以下の通り。
┣ .vscode/ # vscode用の設定記述
┣ src/ # ソースコードはここに置く
┃ ┗ main.py # エントリーポイント
┣ tests/ # テストコードはここに置く
┃ ┗ test_main.py
┣ .flake8 # flake8の設定
┣ .gitignore
┣ README.md
┣ poetry.lock
┗ pyproject.toml
src/main.py
のif __name__ == "__main__":
にメイン処理を書く。
テンプレートは足し算のサンプル。
def addition(num1: float, num2: float):
return num1 + num2
if __name__ == "__main__":
print("Please enter two numbers.")
try:
num1 = float(input("num1: "))
num2 = float(input("num2: "))
except ValueError:
print("Invalid input. Please enter number.")
exit()
result = addition(num1, num2)
print(f"{num1} + {num2} = {result}")
後述するが、task run
でsrc/main.py
を実行できる。
> task run
Please enter two numbers.
num1: 5
num2: 3
5.0 + 3.0 = 8.0
tests
フォルダにはテストコードを書く。
from src.main import addition
def test_addition():
result = addition(2, 3)
assert result == 5
task test
でpytestによるテストを実行できる。
> task test
====================== test session starts =======================
platform win32 -- Python 3.10.0, pytest-7.2.1, pluggy-1.0.0
rootdir: ...
collected 1 item
tests\test_main.py . [100%]
======================= 1 passed in 0.02s ========================
機能
poetry shell
で仮想環境に入ったあと、以下のコマンドが使える。
-
task run
: src/main.py を実行 -
task lint
: flake8 で lint -
task build
: pyinstaller で exe化 -
task build-one
: pyinstaller で exe化 (+ 1つのファイルにまとめる) -
task test
: pytest 実行
また、vscodeでファイル保存時、自動フォーマットが動いてくれる。
ちょっとした解説とカスタマイズのしかた
以下はもう少し構成が知りたい人と、一部カスタマイズして使いたいな~と思った人向け。
リンター・フォーマッター
リンターはflake8、フォーマッターはblackを採用している。
選定はこちらの記事を参考にした。
どちらの設定もデフォルトのままでいいかなと思っているが、flake8とblackのルールに一部競合するところがあるらしいので、その部分だけflake8の設定を変えてあげている。
[flake8]
max-line-length = 88
extend-ignore = E203
また、VSCodeでファイルを保存したとき、blackで自動フォーマットしてほしいため、vscodeの設定ファイルを以下のようにしている。
{
"python.formatting.provider": "black",
"editor.formatOnSave": true
}
flake8をカスタマイズしたい場合は、以下の公式ドキュメントを参考に.flake8
に追記すると良いだろう。
blackのカスタマイズは以下ご参考に。
テスト
テストモジュールはpytestを採用。
選定は以下の記事を参考にした。
詳しい解説は私自身まだ十分に使いこなせていないため省略するが、
pytestは、test
から始まるファイルのtest
から始まる関数を対象にするらしいので注意。
タスク定義
タスク定義にはtaskipyを使っている。
taskipyはPythonのタスクランナーである。
taskipyを使うとpyproject.toml
にタスクを定義することができる。
例えば、今回作成したテンプレートのpyproject.toml
の下には以下の記述がある。
[tool.taskipy.tasks]
run = "poetry run python src/main.py"
lint = "poetry run flake8 src --show-source --statistics"
build = "poetry run pyinstaller -y src/main.py"
build-one = "poetry run pyinstaller -y src/main.py --onefile"
test = "poetry run pytest"
このようにタスク名 = "実行したいコマンド"
としてあげると、task タスク名
で実行したいコマンド
が実行される。
src/main.py
を実行するためにpython src/main.py
などと打つことなくtask run
のように短いコマンドかつ意味のあるコマンドで実行できるためとても便利。
加えて、fastapiのプロジェクトの場合はrun = "poetry run uvicorn src.main:app"
と書き換えてあげたり、プロジェクトによってタスク名に合わせたコマンドに修正してあげることで、「どのプロジェクトでも実行したいときはtask run
!」と統一することができる。
実行ファイル化
こちらは利用できるケースが限られているが、ものによってはpyinstallerというモジュールを使うことで実行ファイル化(exe化)することができる。
実行ファイル化できてしまえばPython環境が要らなくなるので配布しやすくなる。
適切なPythonバージョンをインストールしてもらって、pipで必要なモジュールを全部インストールしていもらって…などせずとも、exeファイル一個投げてダブルクリックしてもらうだけで動くのだ。
実際にPythonで作ったものをpyinstallerを使ってexeファイル化して配布などもしてみたりしている。
(コードは全然大した内容じゃないが、ダウンロードしてすぐ使える形式で配布しているだけで、なんか中身があるように見える)
前述の通り、task build
やtask build-one
でpyinstallerが走るように設定している。
実行すると、上手くいけばdist/
ディレクトリの中にexeファイルが生成されるはずである。
特にtask build-one
はファイルを完全に一つのファイルにまとめてくれるので、基本的にこっちを使っている。(開発のときはtask build
の方が早いかも?)
poetry管理外のバイナリに依存していたり、fastapiなどの単純にsrc/main.pyを実行するわけではないサーバ系だったり、なんか必要なライブラリをpyinstallerが網羅してくれなかったり(transformers使っているプロジェクトで直面した)する場合は、色々な設定をしないと実行ファイル化できないので、そこは調べてがんばってください…。
最後に
自分用のテンプレートがあると、何か作りたくなったときに一瞬で環境ができるのでとても快適です。
みなさんも自分用のテンプレートを作ってみてはいかがでしょうか?
また、「このテンプレートのこの設定方法あまり推奨されないよ!」だったり、「こっちのライブラリの方がいいかも!」だったり、「このライブラリも追加で使ってみない?」などありましたら、ぜひコメントいただけると嬉しいです。