Pythonのプロジェクトの始め方

Pythonでプロジェクト管理を行う方法について調べたことをまとめた
Python
venv
rye
pip
virtual environment
Published

February 15, 2024

Modified

September 17, 2024

Pythonプロジェクト管理について

Pythonのプロジェクト管理を行うツールとしてはさまざまなものがある。 ここでは、自分が触ってみたものについての簡単なメモを残しておく。

Note

(2024/2/15) ひとまずRyeを使う。わからなくなったらRyeのところだけ見る。

これまでにPythonのモジュールをパッケージ化するためのエコシステムと、 仮想環境の構築や依存関係を管理する手法が多数開発されてきた。 すこしPythonで解析を行うだけならばこのような知識は必要ないかもしれないが、 Pythonの解析環境の管理にも依存関係を管理するツールを適用することができれば、 解析の再現性を保つことができるので学んでおくとよい。

パッケージング

パッケージ化とは、Pythonのコード(モジュール)を配布・インストールするために、 PEP-517/518で策定された標準に従う形式で、配布可能な状態にまとめる作業。 ソースコードを配布する「ソースディストリビューション」と、 ビルド産物を配布する「ビルドディストリビューション」の二つの方式がある。 作成したディストリビューションはPython Package Index (PyPI)に登録することで公開できる。

依存関係の管理

パッケージあるいはプロジェクトで使用する他のプログラムについての依存関係の解決を行う。 一つのコンピューター上に複数のプロジェクトがある場合は、 仮想環境を作ってプロジェクト間で環境を分離する必要がある。

仮想環境の提供

プロジェクトごとに環境を分離するための仕組みを提供する。 依存関係にあるライブラリを分離するだけでなく、 場合によってはPython本体のバージョンも管理することができるものもある。

関連ツールのリスト

Pythonにおける環境管理(Pythonインタプリタ、パッケージ)やパッケージング、仮想環境の構築などを行うツールは、 非常に多くのものが開発・公開されている。 メモとしてそれらの関連するツールをリストアップしておく。

  • distutils Python3.12から無くなった
  • setuptools
    • easy_install
  • virtualenv
    • venv
  • pip
  • pipenv
  • pyenv
  • conda
  • poetry
  • pdm
  • rye

venv

venvはPython3.3から標準ライブラリに入った仮想環境を構築・管理するモジュール。 別の仮想環境管理ライブラリvirtualenvのサブセットが公式に取り込まれた。

仮想環境の作成

適当なディレクトリを作成し、その中に入ってシェルで以下のコマンドを実行すると、 仮想環境が作成される。

python3 -m venv test_venv

上の例では、test_venv が仮想環境を保存するディレクトリ名(以降ではENV_DIRとする)となっていて、 これは自由に変更したり、あるいは複数作成することができる。

仮想環境への切り替え

作成した仮想環境に切り替えるときには、${ENV_DIR}/bin/activateを実行する。

${ENV_DIR}/bin/activatebashのスクリプトで、${ENV_DIR}/binにパスを通す。 ${ENV_DIR}/binには、仮想環境作成時に使用したpython3へのシンボリックリンクがあり、 仮想環境内でのpython3の実行ではこのリンクが呼び出される。

また、この${ENV_DIR}/bin/activateには、deactivate関数が定義されており、 仮想環境内でこのdeactivateを呼ぶことで、仮想環境を抜けることができる。

# activateを実行することで仮想環境を有効化され、
# 仮想環境内でdeactivateを呼び出すことで仮想環境を抜ける
# 仮想環境が有効化されているとプロンプトが変わる
PS1="#>"
echo "prompt before activated : '${PS1}'"
. test_venv/bin/activate
echo "prompt after activated  : '${PS1}'"
deactivate
echo "prompt after deactivated: '${PS1}'"
#> prompt before activated : '#>'
#> prompt after activated  : '(test_venv) #>'
#> prompt after deactivated: '#>'

ライブラリのインストール

外部ライブラリのインストールには後述のpipモジュールがよく用いられる。 pipを利用した外部ライブラリのインストールは、以下のコマンドで行う。

python3 -m pip install setuptools
Collecting setuptools
  Using cached setuptools-75.1.0-py3-none-any.whl.metadata (6.9 kB)
Using cached setuptools-75.1.0-py3-none-any.whl (1.2 MB)
Installing collected packages: setuptools
Successfully installed setuptools-75.1.0

仮想環境内でインストールしたライブラリは.venv/libに配置され、 インストール済みライブラリの検索もここから行われる。

python3 -m pip list
Package    Version
---------- -------
pip        24.0
setuptools 75.1.0

仮想環境の終了

仮想環境を終了するには、仮想環境が有効になっている状態でdeactivate関数を呼び出す。

deactivate

仮想環境の共有

仮想環境で使用しているライブラリ一覧を作成して、別の場所で環境を共有することができる。

ライブラリ一覧の作成はpip freezeコマンドの標準出力をファイル (requirements.txtというファイル名で保存することが多い)に記録し、 記録したファイルをpip install -r {freeze_stdout}のように読み込ませることで、 記録したライブラリ情報をもとにインストールを行うことができる。

# ライブラリ一覧の作成
python3 -m pip freeze > venv_requirements.txt
deactivate
cat venv_requirements.txt
setuptools==75.1.0
# venv_requirements.txtに記載されたライブラリのインストール
python3 -m venv another_venv
. another_venv/bin/activate
python3 -m pip install -r venv_requirements.txt
Collecting setuptools==75.1.0 (from -r venv_requirements.txt (line 1))
  Using cached setuptools-75.1.0-py3-none-any.whl.metadata (6.9 kB)
Using cached setuptools-75.1.0-py3-none-any.whl (1.2 MB)
Installing collected packages: setuptools
Successfully installed setuptools-75.1.0

pip

pipは外部パッケージのインストールによく使われるツール。

pipモジュールがない時(ensurepipによるpipの入手)

Pythonインタプリタからpipモジュールを実行したときに、pipモジュールが無い旨のエラーメッセージが出た場合は、 pipモジュールを含まないPythonインタプリタを利用している(後述のryeでインストールされるものなど)。 そのような環境でpipを使用したい場合は事前にインストールする必要がある。 pip自体のインストールは標準ライブラリのensurepipモジュールを利用することでできる。

ensurepipはすでにpipコマンドがインストールされている場合はそれを利用し、 まだインストールされていない場合は適切なものをインストールする。

# ensurepipを実行してpipをインストールする。
python3 -m ensurepip
Looking in links: /var/folders/27/6lbc0j2n5rl8_lcz577q4syw0000gn/T/tmp7r93y8dz
Processing /var/folders/27/6lbc0j2n5rl8_lcz577q4syw0000gn/T/tmp7r93y8dz/pip-24.0-py3-none-any.whl
Installing collected packages: pip
Successfully installed pip-24.0

pip searchはエラーになる

PyPIからパッケージを検索するコマンド、pip searchはエラーが出て使うことができない。

python3 -m pip search pip
ERROR: XMLRPC request failed [code: -32500]
RuntimeError: PyPI no longer supports 'pip search' (or XML-RPC search). Please use https://pypi.org/search (via a browser) instead. See https://warehouse.pypa.io/api-reference/xml-rpc.html#deprecated-methods for more information.

これはPyPIがpip searchをもうサポートしないためらしい。

代わりにpip_searchコマンドをインストールして利用することができる。

pip-search

A package to search like pip used to, via PyPi

https://pypi.org/project/pip-search/

# pip_searchコマンドのインストール
python3 -m pip install pip_search 1>/dev/null 2>/dev/null

# pip_searchコマンドを使ってパッケージを検索
pip_search dnaio
                     🐍 https://pypi.org/search/?q=dnaio 🐍                     
┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Package                  ┃ Version ┃ Released   ┃ Description                ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 📂 dnaio                 │ 1.2.1   │ 16-06-2024 │ Read and write FASTA and   │
│                          │         │            │ FASTQ files efficiently    │
│ 📂 fastq-filter          │ 0.3.0   │ 01-06-2022 │ A fast FASTQ filter        │
│                          │         │            │ progam.                    │
│ 📂 filter-illumina-index │ 1.0.5   │ 14-12-2023 │ Filter a Illumina FASTQ    │
│                          │         │            │ file based on index        │
│                          │         │            │ sequence                   │
└──────────────────────────┴─────────┴────────────┴────────────────────────────┘

rye

ここまで、仮想環境の構築にはvenv、外部ライブラリの管理にはpipが利用できることを紹介してきた。 Rye(コマンドはrye)はPythonの仮想環境管理や外部ライブラリ管理に加えて、 Pythonインタプリタ自身の管理も可能なオールインワンなツールで、 高速化のためにrye自身はRustで実装されている。 また、パッケージ管理の高速化のために、従来のpipの代わりに同じくRustで実装されているuvを使用することができる。

利用しているryeのバージョン

rye --version
rye 0.39.0
commit: 0.39.0 (bf3ccf818 2024-08-21)
platform: macos (aarch64)
self-python: cpython@3.12.4
symlink support: true
uv enabled: true

プロジェクト作成

プロジェクトの初期化にはrye initサブコマンドを用いる

# プロジェクト用に適当なディレクトリを作成し、移動する
mkdir -p rye_project; cd rye_project

# rye initでプロジェクトを初期化する
rye init

# パッケージ開発をしない場合は--virtualフラグをつける
# rye init --virtual
success: Initialized project in /Users/t_arae/blog/posts/2024/2024-02-15-python-hello-world/rye_project/.
  Run `rye sync` to get started

プロジェクト内で使用するPythonインタプリタは、rye pinサブコマンドで指定する。

# rye pinでプロジェクトで使用するPythonインタプリタのバージョンを指定する
rye pin cpython@3.11
pinned 3.11.9 in /Users/t_arae/blog/posts/2024/2024-02-15-python-hello-world/rye_project/.python-version

ryeで変更した設定はpyproject.tomlファイルに記録されており、 rye syncサブコマンドを使ってプロジェクト内のvirtualenvの情報を このpyproject.tomlを基にアップデートする。

rye sync
Initializing new virtualenv in /Users/t_arae/blog/posts/2024/2024-02-15-python-hello-world/rye_project/.venv
Python version: cpython@3.11.9
Generating production lockfile: /Users/t_arae/blog/posts/2024/2024-02-15-python-hello-world/rye_project/requirements.lock
Generating dev lockfile: /Users/t_arae/blog/posts/2024/2024-02-15-python-hello-world/rye_project/requirements-dev.lock
Installing dependencies
Resolved 1 package in 1ms
Prepared 1 package in 295ms
Installed 1 package in 0.81ms
 + rye-project==0.1.0 (from file:///Users/t_arae/blog/posts/2024/2024-02-15-python-hello-world/rye_project)
Done!

以上を実行すると、プロジェクト内に以下のようなディレクトリおよびファイルが作成される。

project_name/
├── .gitignore
├── .python-version
├── .venv/
|   ⋮
|   └── .gitignore
├── README.md
├── pyproject.toml
├── requirements.lock
├── requirements-dev.lock
└── src/
    └── my_project
        └── __init__.py

ライブラリの管理

ryeではプロジェクトで依存する外部パッケージの管理も行うことができる。

プロジェクトで依存するパッケージの追加は、rye add {追加したいパッケージ名}で行う。 この時、パッケージのバージョンを指定することもできる。 追加した依存情報はrequirements.lockおよびrequirements-dev.lockに記録される。 開発環境でのみ利用するパッケージは、--devフラグをつけてrye addすると requirements-dev.lockに記録される。

# 依存の追加
rye add --quiet "cowsay>=6.0"
rye add --quiet --dev setuptools
# lockファイルの確認
grep '==' requirements*.lock
requirements-dev.lock:cowsay==6.1
requirements-dev.lock:setuptools==75.1.0
requirements.lock:cowsay==6.1
# インストールしたパッケージは、仮想環境を有効化すると使用できる
. .venv/bin/activate
python3 -c 'import cowsay; print(cowsay.cow("hello python"))'
  ____________
| hello python |
  ============
            \
             \
               ^__^
               (oo)\_______
               (__)\       )\/\
                   ||----w |
                   ||     ||
None

インストールしたパッケージを除くにはrye removeサブコマンドを使う。

rye remove --quiet cowsay
python3 -c 'import cowsay; print(cowsay.cow("hello python"))'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'cowsay'

プロジェクトの確認

プロジェクトの状態を確認するには、rye showサブコマンドを使用する。

rye show
project: rye-project
path: /Users/t_arae/blog/posts/2024/2024-02-15-python-hello-world/rye_project
venv: /Users/t_arae/blog/posts/2024/2024-02-15-python-hello-world/rye_project/.venv
target python: 3.11
venv python: cpython@3.11.9
virtual: false
configured sources:
  default (index: https://pypi.org/simple/)

また、プロジェクトの依存関係の一覧は、rye listサブコマンドで確認できる。

rye list
-e file:///Users/t_arae/blog/posts/2024/2024-02-15-python-hello-world/rye_project
setuptools==75.1.0

仮想環境

rye initでプロジェクトを初期化すると自動的に仮想環境が作成される。

仮想環境に入るにはvenvと同じように、. .venv/bin/activateを実行すれば良い。 rye syncを実行していれば、仮想環境内ではryeが提供するツールチェインや、 設定したコマンドを実行できる。 仮想環境を抜ける時は、環境内でdeactivateを実行すればよい。

# 仮想環境の有効化
rye sync
. .venv/bin/activate

# 環境内で実行できるコマンドのリスト
rye run --list

# 仮想環境の無効化
deactivate

プロジェクトの設定

Ryeはpyproject.tomlで設定を行う。 pyproject.tomlはPEP-518で提案されたファイル名およびフォーマットで、 Pythonプロジェクトのビルド依存関係を指定する方法を規定する。 標準策定の経緯は以下のリンク先の記事が参考になる。

Python パッケージングの標準を知ろう | Recruit Tech Blog

Python パッケージングの標準を知ろうです。リクルートの社内組織やプロダクト開発、最新のTech関連情報などを紹介しています。

https://blog.recruit.co.jp/rls/2019-12-25-python-packaging-specs/

ここで重要なのは、サードパーティのツールはそれぞれのツールの独自設定を、 pyproject.toml内のtool.${ツール名}テーブルに記録し利用することができるということである。 つまりRye独自の設定はtool.rye.~~~に記録される。

  • project.dependencies
    • 依存関係が記録される。rye add, rye removeで自動的に修正される。
  • project.scripts
    • 環境にインストールされるスクリプトを指定する。指定したスクリプトはrye syncした後にrye run ~~~で実行することができる。
  • tool.rye.dev-dependencies
    • 開発環境でのみ必要となる依存関係。rye add --devで修正できる。

参考

パッケージングについての解説

Pythonのパッケージングと配布の全体像

https://zenn.dev/zerebom/articles/60d5ad4b18c901

poetry, pdm, ryeについての簡単な解説

Environment Tools: PDM, Poetry and Rye

We bring this series on environment tools to a close by looking at two older tools - PDM and Poetry - and one new entrant, Rye.

https://www.playfulpython.com/environment-tools-pdm-poetry-rye/

venvが仮想環境を実現する実際の動き

venvが動作する仕組みを調べてみた - えんでぃの技術ブログ

Pythonのvenvがどのような仕組みで動作するかを調べてみました。ソースコードをには一切触れず、ドキュメントに書かれたことをベースにわかりやすくご説明します。

https://endy-tech.hatenablog.jp/entry/how_venv_works_in_python

まとめ

特に理由がなければryeを使用すればよさそう。