プログラミング初心者がアーキテクトっぽく語る

見苦しい記事も多数あるとは思いますが訂正しつつブログと共に成長していければと思います

uvを使ったPythonプロジェクトのセットアップ

Pythonのコードの書き方は人それぞれです。

Pythonプロジェクトのフォルダ構成、パッケージ構成にも色々なものがあります。

私自身、今まで色々と変遷してきまきました。

今回は「今はこんな感じで作ってるよ」というのをご紹介したいと思います。

簡単なスクリプトを書く場合は簡素化することもありますが、大体こんな感じでやってます。


前提

IDEはPyCharm(もしくはIntelliJ + Pythonプラグイン)、管理ツールはuvが前提です。

uvの導入や基本操作についてはこちらを参照してください。

architecting.hateblo.jp


検討

以下のことを決めます。

  • プロジェクト名(=パッケージ名)
  • そのプロジェクトで使うPythonバージョン
  • そのプロジェクトのGitで使う名前とメールアドレス

1. プロジェクトフォルダ作成

uv init --python <Pythonバージョン> <プロジェクト名>
cd <プロジェクト名>

プロジェクトフォルダの中に色々とファイルが作成されます。

% ls -a
.       ..      .git        .gitignore  .python-version README.md   main.py     pyproject.toml
%

プロジェクトフォルダ直下にあるmain.pyは削除してしまうことが多いです。


2. 仮想環境作成

uv venv

.venvディレクトリが作成されます。 仮想環境に入りたい場合はsource .venv/bin/activateで入ります。 出るときはdeactivateです。


3. IDEPython Interpreter設定

IDEでプロジェクトフォルダを開きます。 先程作成した.venv/bin/配下のPythonを、プロジェクトのInterpreterに指定します。

PyCharmなら、PyCharm > Settings > Project:<プロジェクト名> > Python Interpreter で設定します。

IntelliJなら、File > Project Structure > Project Settings > Project > SDK で設定します。


4. Git設定

このプロジェクトで使用するユーザ名、メールアドレスを設定します。

git config --list
git config user.name "My Name"
git config user.email "myname@example.com"

なにも設定しない場合、globalに設定されているものが使われます。 globalにも設定されていない場合はcommit時に怒られます。

なおgit inituv init時に実施済みなので不要です。


5. .gitignoreの編集

.gitignoreがuv init時に作成され、Python開発向けの最小限の項目が記載されてます。 MacでPyCharm/IntelliJを使うなら以下の2つも追記しましょう。

.DS_Store
idea/

コーディング中、除外したいものが出てきたら都度追加します。 git statusなどでこまめに監視対象ファイルを確認するようにしましょう。


6. IDEでSources rootとTest Sources Rootを作成

src/ディレクトリとtests/ディレクトリを作成します。

<プロジェクト名>/
 ├── src/
 └── tests/

src/はIDEで「Sources Root」に設定します。 右クリックして「Mark Directory as」から選択できます。

同様にtests/はIDEで「Test Sources Root」に設定します。

rootに設定しておくとIDEからコードや単体試験を実行したとき、sys.pathをいい感じにしてModuleNotFoundErrorを防いでくれるので、快適に作業できます。

逆に言うと、「IDEからは実行できるのに外部ターミナルからpythonコマンドで呼び出すとModuleNotFoundErrorで動かない!」というのは外部ターミナルから呼び出したとき、sys.pathにSources Rootが入っていないことが原因です。 そういうときはsys.pathを見直しましょう。


7. コーディング

ここからはコーディングタイムです。 コードはsrc/に書き、対応する単体試験はtests/に書きます。

実際には私はsrc/やtests/を作成する前にプロジェクトフォルダ直下で適当にコーディングを開始して、ファイルがいくつか出来てきた段階でsrc/とtests/を作ることが多いです。 行き当たりばったりな性格なので。。。


8. パッケージ作成

ある程度、コードが溜まってくるとパッケージに分類したくなります。 以下のように分けます。

<プロジェクト名>/
 ├── src/
 │   └── <プロジェクト名/>
 │         ├── mypkg1
 │         └── mypkg2
 │   
 └── tests/
     ├── <プロジェクト名>_
     │     ├── mypkg1_
     │     └── mypkg2_
     └── resources

src/直下にはプロジェクト名と同じパッケージを作成します。 さらに細かく分類したい場合はその下にさらにパッケージを作成します。(mypkg1, mypkg2)

(注:上のサンプルでは記載を省略してますが各パッケージの中には空の__init__.pyがあります)

tests/配下は基本的にsrc/配下と同じ構成、命名にします。 これはJavaなどではよく見る構成ですが、Pythonではあまり一般的ではないようです。 これをすると単体試験実行時にsys.path地獄からModuleNotFoundErrorオバケがよく出てくるようになります。 そこでパッケージ名の後ろに「_」をつけて、魔除けにしてます。 一般的ではないようですが、どこかで見かけて以来、便利なので真似してます。

Pythonでは上記のようにsrc/直下にはプロジェクト名と同じパッケージが1つのみあることが一般的ですが、下記のように複数配置することも勿論、可能です。

<プロジェクト名>/
 ├── src/
 │   └── <プロジェクト名/>
 │   └── mypkg
 └── tests/
     ├── <プロジェクト名>_
     ├── mypkg_
     └── resources

9. パッケージ追加

uv addを使います。

uv add <パッケージ名>
uv add --dev <開発環境用パッケージ名>

uv addで追加すると自動でpyproject.tomlへ記載してくれます。 pyproject.tomlは後でpipインストール可能な配布形式を作成するときに役に立ちます。 pip installuv pip installだとpyproject.tomlへ記載されないので気をつけましょう。

なお、pyproject.tomlのproject.dependenciesに記載された依存関係はpip install .で一括インストールできます。 pyproject.tomlはuvが使えない環境に移行しても使い続けることができる優れモノです。


10. pipでインストール可能な配布形式を作成する

完成したら配布可能な形式にします。

pipでインストール可能な形式にしたい方はこちらをご覧ください。

architecting.hateblo.jp

11. 実行形式にする

WindowsMacLinuxで実行可能な実行ファイルにすることもできます。 ただしuvではできません。 pyinstallerやnuitkaを利用する必要があります。

興味ある方はこちらをご覧ください。

architecting.hateblo.jp


感想

uvはひとつで色々やってくれて楽ですね。 どこかで見たことあるコマンドやオプションが多く、学習コストが低いのもありがたいです。

今はこんなところで落ち着いてます。 今後もよりよりやり方があれば取り入れていきたいです。