君たちはどうPythonするか
毎年Python管理ツールを乗り換える者たちへ
pythonみすてむずこの記事は、みすてむず いず みすきーしすてむず Advent Calendar 2025の16日目の記事です。
これは2枚目
前書き
https://misskey.systems/notes/9ra1kyab0e
pyenv, anaconda, それに launchpad(PPA) を勧めるあたり一昔前かそれより前時代の感が出ています。
最近は「Ryeにしたばかりのプロジェクトをuvに移行する」という景色もあったことでしょう。
私はこのところPythonを中心に作業をすることがなく、なんとなくryeやuvがあるようだという認識なのでこの機会に整理します。
どのくらい疎くなっていたか。pyenv+venvを基本として、pipenvは1回試した気がして、pipでpyproject.tomlを使えると知らなかったくらいです。
ツール別の使い方ガイドではなく機能分類ごとに違いと変遷を見ていきます。
それで何を使えばいいか
と聞かれたら
- uv
- とりあえずこれでいいです。
- 人にスマートフォンのおすすめを聞かれたらiPhoneでいいよと答える感じです。
- 任意のバージョン管理ツール + venv + pip/pip-tools
- 世の8割の用途はこれで十分です。(要出典)
- パッケージ配布をしないならば困ることは少ないです。
- ツールが何をしているかわかっていればこれでいいです。1
- 世の8割の用途はこれで十分です。(要出典)
- Anacondaまたは派生
- condaにしかパッケージが無く代替手段がない時に考えます。
と答えますが結局のところ制約はその人、その時にしかわからないのでツールが何を担保してくれるのか、何を支援してくれるのかを知っておくべきです。2
注意
Ryeは統合的なPythonプロジェクト管理ツールでしたが現在はuvへの移行が推奨されています。
https://github.com/astral-sh/rye/tree/0.44.0
If you’re getting started with Rye, consider uv, the successor project from the same maintainers.
While Rye is actively maintained, uv offers a more stable and feature-complete experience, and is the recommended choice for new projects.
新規プロジェクトに使うべきではありませんが、ツール比較にとって重要な存在なので含めています。
環境管理を主題としているため、環境管理とともに開発に重要なlinter/formatter、テストランナー、型検査ツールについては触れていません。
ワークスペース機能も話が増えるので触れていません。
Anacondaは系統が異なるため深く触れずに短い説明にとどめています。
ツールの選定はメジャーだと思っているものを選びました。3
この記事の動作例の環境は特にことわりがない限り、OSはLinux(Debian13/Ubuntu24.04)コンテナ、シェルはBashを前提としています。
ショートカット
忙しい年末の閲覧順
- Part 1: Pythonランタイム > 1.4 ツール比較一覧(令和最新版) を見る。(1分)
- Part 1: Pythonランタイム > 1.1 手動でPythonを動かしてみる をやる。(15分+ビルド時間)
- 各Partの比較を見る。(5分)
残りの内容は辞書的な使い方をお薦めします。
これからここを読む人は文章を読み込むよりも仮想マシンやコンテナで使い捨てできる環境を作って手を動かした方が理解は速く、記憶も深くなります。4
Part 1: Pythonランタイム
便利ツールのGetting Startedにあるcurl https://example.org/awesome-tool/install.sh | shのような方法でPythonが動いても何が起こっているのかわからないので自分で手を動かしてください。
1.1 手動でPythonを動かしてみる
Pythonが無い環境にPythonを入れましょう。
debian:trixieコンテナを使います。
$ docker run -it --rm --hostname "x" debian:trixie bash
コンテナ内
root@x:/# cat /etc/os-release | head -n 1
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
root@x:/# python
bash: python: command not found
root@x:/# python3
bash: python3: command not found
わかりやすい環境のためにdebianコンテナを使いますが、この後の手順は非コンテナ環境でもpythonコマンドがあっても問題はありません。
Step 1: Pythonバイナリを落としてビルドする
私たちはパッケージマネージャーに甘えてソースからOSSを使う喜びを忘れているので、Pythonをソースからビルドします。
まず、ビルドツールと依存ライブラリを入れます。5
root@x:/# apt update; apt install -y build-essential wget \
libssl-dev \
zlib1g-dev \
libbz2-dev \
libreadline-dev \
libsqlite3-dev \
libncurses5-dev \
libncursesw5-dev \
xz-utils \
tk-dev \
libffi-dev \
liblzma-dev \
libgdbm-dev \
libnss3-dev \
uuid-dev
https://www.python.org/downloads/source/ から公式のソースファイルをダウンロードしてビルドします。
作業ディレクトリは次のようにします。
/opt: ダウンロードディレクトリ/opt/Python-3.11.0: ソースコード展開ディレクトリ/opt/python-3.11.0: ビルド済みバイナリ配置ディレクトリ (小文字)
ソース取得と展開をします。
root@x:/# cd /opt
root@x:/opt# wget https://www.python.org/ftp/python/3.11.0/Python-3.11.0.tgz
root@x:/opt# tar xf Python-3.11.0.tgz
root@x:/opt# ls
Python-3.11.0 Python-3.11.0.tgz
root@x:/opt# cd Python-3.11.0
ビルドとインストールを実行します。6
root@x:/opt/Python-3.11.0# ./configure --prefix=/opt/python-3.11.0
root@x:/opt/Python-3.11.0# make -j"$(nproc)"
root@x:/opt/Python-3.11.0# make install
root@x:/opt/Python-3.11.0# cd /opt
root@x:/opt# ls -F
Python-3.11.0/ Python-3.11.0.tgz python-3.11.0/
root@x:/opt# ls /opt/python-3.11.0/bin/
2to3 idle3 pip3 pip3.11 pydoc3.11 python3-config python3.11-config
2to3-3.11 idle3.11 pip3.10 pydoc3 python3 python3.11
ビルドできたので、起動します。
root@x:/opt# /opt/python-3.11.0/bin/python3
Python 3.11.0 (main, Nov 16 2025, 11:36:43) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
root@x:/opt#
配置はこんな感じです。
/opt
└── python-3.11.0
└── bin/
└── python3
Step 2: PATH環境変数を理解する
Pythonが動いたので、これで開発したいです。
毎回絶対パスで打ち込むのはつらい。
ここは python3 で
root@x:/opt# cd
root@x:~# mkdir app01
root@x:~# cd app01
root@x:~/app01# python3
bash: python3: command not found
なぜだ・・・
PATH環境変数
シェルが実行コマンドを探すディレクトリのリストです。PATH環境変数に書かれている順番でディレクトリを探して最初に見つかったものを実行します。
root@x:/opt# cd
root@x:~# python3
bash: python3: command not found
root@x:~# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
コロン区切りでPATHの先頭にあるディレクトリが優先されます。
| 対象 | 走査順 |
|---|---|
| /usr/local/sbin/python3 | ↓ |
| /usr/local/bin/python3 | ↓ |
| /usr/sbin/python3 | ↓ |
| /usr/bin/python3 | ↓ |
| /sbin/python3 | ↓ |
| /bin/python3 | ↓ |
bash: python3: command not found |
シェルが知っている場所にPythonがありません。
PATH環境変数にStep 1でビルドしたPythonのbinディレクトリを追加します。
root@x:~/app01# export PATH="/opt/python-3.11.0/bin:$PATH"
root@x:~/app01# echo $PATH
/opt/python-3.11.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
root@x:~/app01# python3 --version
Python 3.11.0
ビルドしたPythonが見つかりました。
| 対象 | 走査順 |
|---|---|
| /opt/python-3.11.0/bin/python3 | ここで走査終了 |
| /usr/local/sbin/python3 | |
| …(省略) |
配置はこんな感じです。
/opt/
└── python-3.11.0/
└── bin/
└── python3
$HOME
└── app01/
Step 3: モジュールのサーチパス
Pythonが動いたのでライブラリを使ってみます。
root@x:~/app01# python3
Python 3.11.0 (main, Nov 16 2025, 11:36:43) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'requests'
当然ですがまだimportできません。
Pythonはどうやってモジュールを探すのか?
sys.pathを見ます。
>>> import sys
>>> for p in sys.path:
... print(p)
...
/opt/python-3.11.0/lib/python311.zip
/opt/python-3.11.0/lib/python3.11
/opt/python-3.11.0/lib/python3.11/lib-dynload
/opt/python-3.11.0/lib/python3.11/site-packages
>>> exit()
sys.pathはPythonがモジュールを探すディレクトリのリストです。
上から順番に探して最初に見つかったモジュールをimportします。
試しにrequestsをインストールしてみます。
root@x:~/app01# pip3 install requests
Collecting requests
Downloading requests-2.32.5-py3-none-any.whl (64 kB)
...(省略)
Successfully installed certifi-2025.11.12 charset-normalizer-3.4.4 idna-3.11 requests-2.32.5 urllib3-2.5.0
root@x:~/app01# ls -F /opt/python-3.11.0/lib/python3.11/site-packages/
README.txt distutils-precedence.pth requests/
_distutils_hack/ idna/ requests-2.32.5.dist-info/
certifi/ idna-3.11.dist-info/ setuptools/
certifi-2025.11.12.dist-info/ pip/ setuptools-65.5.0.dist-info/
charset_normalizer/ pip-22.3.dist-info/ urllib3/
charset_normalizer-3.4.4.dist-info/ pkg_resources/ urllib3-2.5.0.dist-info/
ビルドしたPythonのディレクトリの下のsite-packagesにライブラリがインストールされました。これがグローバルなインストールです。 ls結果の上段右側にrequestsディレクトリもあります。これで、このpython3を使う全てのプロジェクトでrequestsが使えます。
root@x:~/app01# python3
>>> import requests
>>> requests.__file__
'/opt/python-3.11.0/lib/python3.11/site-packages/requests/__init__.py'
>>> exit()
今の構成はこうなっています。
/opt/
└── python-3.11.0/
├── bin/
│ └── python3
└── lib/
└── python3.11/
└── site-packages/ ← グローバルなモジュールインストール先
└── requests/
$HOME/
└── app01/
Step 4: グローバルインストールとパッケージ
app02を作ります。
root@x:~/app01# cd
root@x:~# mkdir app02
root@x:~# cd app02
app02でもrequestsが使えます。
root@x:~/app02# python3
>>> import requests
>>> requests.__version__
'2.32.5'
>>> exit()
app02ではflaskも使いたいのでインストールします。
root@x:~/app02# pip3 install flask
Collecting flask
Downloading flask-3.1.0-py3-none-any.whl (102 kB)
...
Successfully installed Jinja2-3.1.4 MarkupSafe-3.0.2 Werkzeug-3.1.3 blinker-1.9.0 click-8.1.7 flask-3.1.0 itsdangerous-2.2.0
app01に戻ってみます。
root@x:~/app02# cd ~/app01
root@x:~/app01# python3
>>> import flask
>>> flask.__version__
<stdin>:1: DeprecationWarning: The '__version__' attribute is deprecated and will be removed in Flask 3.2. Use feature detection or 'importlib.metadata.version("flask")' instead.
'3.1.0'
>>> exit()
app01はrequestsしか使わないプロジェクトなのにflaskも使えます。
/opt/
└── python-3.11.0/
├── bin/
│ └── python3
└── lib/
└── python3.11/
└── site-packages/ ← 全プロジェクトで共有
├── requests/
└── flask/
$HOME/
├── app01/ ← requestsだけ使いたい
└── app02/ ← requestsとflaskを使いたい。
複数のプロジェクトで同じPythonを使うと、ライブラリがごちゃ混ぜになります。
特に困るのは、プロジェクトごとに異なるバージョンのライブラリを使いたい場合です。
この問題を解決するのが、venvやuvなどのツールです。
Step 5: venvで隔離する
Pythonに標準で組み込まれているvenvを使うと、プロジェクトごとに独立したPythonパッケージ利用環境を作れます。
独立した環境を仮想環境と呼んでいます。
app03を作成します。
root@x:~/app02# cd
root@x:~# mkdir app03
root@x:~# cd app03
venvモジュールで仮想環境を作ります。
格納先は.venvとします。
root@x:~/app03# which python3
/opt/python-3.11.0/bin/python3
root@x:~/app03# python3 -m venv .venv
root@x:~/app03# ls -a
. .. .venv
root@x:~/app03# ls -F .venv
bin/ include/ lib/ lib64@ pyvenv.cfg
.venvディレクトリが作られました。この中にプロジェクト専用のPython環境が入っています。
作業中のシェルで仮想環境を有効化します。
root@x:~/app03# source .venv/bin/activate
(.venv) root@x:~/app03#
プロンプトに(.venv)が表示されました。これで仮想環境が有効になっています。
whichコマンドで確認してみます。
(.venv) root@x:~/app03# which python3
/root/app03/.venv/bin/python3
(.venv) root@x:~/app03# which pip3
/root/app03/.venv/bin/pip3
python3とpip3のパスが仮想環境のものに変わりました。
PATH環境変数を確認してみます。
(.venv) root@x:~/app03# echo $PATH
/root/app03/.venv/bin:/opt/python-3.11.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
仮想環境の/root/app03/.venv/binがPATHの先頭に追加されています。これにより、仮想環境内のpython3やpip3が優先的に使われます。
Pythonのバージョンを確認します。
(.venv) root@x:~/app03# python3 --version
Python 3.11.0
PythonランタイムはビルドしたPython 3.11.0を使っていますが、site-packagesは仮想環境専用のものになっています。
(.venv) root@x:~/app03# python3
>>> import sys
>>> for p in sys.path:
... print(p)
...
/opt/python-3.11.0/lib/python311.zip
/opt/python-3.11.0/lib/python3.11
/opt/python-3.11.0/lib/python3.11/lib-dynload
/root/app03/.venv/lib/python3.11/site-packages ← 仮想環境専用
>>> exit()
インストール済みのパッケージを確認します。
(.venv) root@x:~/app03# pip3 list
Package Version
---------- -------
pip 22.3
setuptools 65.5.0
app01とapp02でインストールしたrequestsやapp02でインストールしたflaskは入っていません。
ここで仮想環境にテストランナーpytestをインストールします。
(.venv) root@x:~/app03# pip3 install pytest
Collecting pytest
Downloading pytest-9.0.1-py3-none-any.whl (373 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 373.7/373.7 kB 5.6 MB/s eta 0:00:00
Collecting iniconfig>=1.0.1
Downloading iniconfig-2.3.0-py3-none-any.whl (7.5 kB)
Collecting packaging>=22
Downloading packaging-25.0-py3-none-any.whl (66 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 66.5/66.5 kB 12.9 MB/s eta 0:00:00
Collecting pluggy<2,>=1.5
Downloading pluggy-1.6.0-py3-none-any.whl (20 kB)
Collecting pygments>=2.7.2
Downloading pygments-2.19.2-py3-none-any.whl (1.2 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.2/1.2 MB 27.5 MB/s eta 0:00:00
Installing collected packages: pygments, pluggy, packaging, iniconfig, pytest
Successfully installed iniconfig-2.3.0 packaging-25.0 pluggy-1.6.0 pygments-2.19.2 pytest-9.0.1
[notice] A new release of pip available: 22.3 -> 25.3
[notice] To update, run: pip install --upgrade pip
pytestコマンドが使えるようになりました。
(.venv) root@x:~/app03# which pytest
/root/app03/.venv/bin/pytest
(.venv) root@x:~/app03# ls .venv/lib/python3.11/site-packages/pytest
__init__.py __main__.py __pycache__ py.typed
(.venv) root@x:~/app03# pytest
================================================================ test session starts ================================================================
platform linux -- Python 3.11.0, pytest-9.0.1, pluggy-1.6.0
rootdir: /root/app03
collected 0 items
仮想環境を無効化します。
(.venv) root@x:~/app03# deactivate
root@x:~/app03# echo $PATH
/opt/python-3.11.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
root@x:~/app03# pytest
bash: pytest: command not found
仮想環境を無効化すると、pytestコマンドは使えなくなります。
root@x:~/app03# python3
>>> import flask
>>> exit()
グローバル環境ではflaskが使えます。app03で仮想環境を作っても、グローバル環境には影響しません。
/opt/
└── python-3.11.0/
├── bin/
│ ├── pip3
│ └── python3
└── lib/
└── python3.11/
└── site-packages/ ← グローバル(app01, app02で共有)
├── requests/
└── flask/
$HOME/
├── app01/ (グローバル環境)
├── app02/ (グローバル環境)
└── app03/
└── .venv/
├── bin/
│ ├── python3 -> /opt/python-3.11.0/bin/python3 (シンボリックリンク)
│ ├── pip3 -> /opt/python-3.11.0/bin/pip3 (シンボリックリンク)
│ └── pytest ← .venv使用環境専用
└── lib/
└── python3.11/
└── site-packages/ ← .venv使用環境専用
└── pytest/
venvを使うと、プロジェクトごとに独立した環境を作れます。他のプロジェクトに影響を与えることなく、必要なライブラリだけをインストールできます。
これ以降はPythonバージョンを指定するためのPATH設定なしに source .venv/bin/activate を実行すればシェルで同じPythonバージョンとパッケージ環境が有効になります。
Step 6: 異なるPythonバージョンを使う
app04では最新のPython 3.12.0を使いたくなりました。
まず3.12.0を3.11.0と同じようにビルドします。
※ パス間違い注意
root@x:~/app03# cd /opt
root@x:/opt# wget https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tgz
root@x:/opt# tar xf Python-3.12.0.tgz
root@x:/opt# cd Python-3.12.0
root@x:/opt/Python-3.12.0# ./configure --prefix=/opt/python-3.12.0
root@x:/opt/Python-3.12.0# make -j"$(nproc)"
root@x:/opt/Python-3.12.0# make install
root@x:/opt/Python-3.12.0# cd
root@x:~# /opt/python-3.12.0/bin/python3 --version
Python 3.12.0
app04を作成します。
root@x:~# mkdir app04
root@x:~# cd app04
どのpython3を使うかはPATH環境変数で決まります。
Step1から続けている場合は、Python3.11.0を指しています。
探索は先頭が優先されるので、そのまま付け足します。
root@x:~/app04# echo $PATH
/opt/python-3.11.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
root@x:~/app04# python3 --version
Python 3.11.0
root@x:~/app04# export PATH="/opt/python-3.12.0/bin:$PATH"
root@x:~/app04# echo $PATH
/opt/python-3.12.0/bin:/opt/python-3.11.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
root@x:~/app04# python3 --version
Python 3.12.0
PATHを変えるだけでバージョンが切り替わりました。
root@x:~/app04# python3
>>> import sys
>>> sys.version
'3.12.0 (main, Nov 16 2025, 12:15:23) [GCC 14.2.0]'
>>> for p in sys.path:
... print(p)
...
/opt/python-3.12.0/lib/python312.zip
/opt/python-3.12.0/lib/python3.12
/opt/python-3.12.0/lib/python3.12/lib-dynload
/opt/python-3.12.0/lib/python3.12/site-packages
>>> exit()
site-packagesのパスが3.12.0のものになっています。これで3.12.0専用のライブラリをインストールできます。
venvを使う場合も、同様にpython3 -m venv .venvを行います。
配置はこうなります。
/opt/
├── python-3.11.0/
│ ├── bin/
│ │ └── python3
│ └── lib/
│ └── python3.11/
│ └── site-packages/
│ ├── requests/
│ └── flask/
└── python-3.12.0/
├── bin/
│ └── python3
└── lib/
└── python3.12/
└── site-packages/
$HOME/
├── app01/ (python-3.11.0, グローバル)
├── app02/ (python-3.11.0, グローバル)
├── app03/ (python-3.11.0, venv)
└── app04/ (python-3.12.0, グローバル)
異なるPythonバージョンを使い分ける方法がわかりました。
ディレクトリを決めてソースコードをダウンロードしてビルドすれば、また新しいバージョンを使いたくなっても大丈夫です。
まとめ
手を動かしてわかったこと:
- Pythonランタイム: ただのバイナリファイル。どこに置いてもいい。
- PATH環境変数: シェルがコマンドを探す場所のリスト。
- sys.path: Pythonがモジュールを探す場所のリスト。
- グローバルインストール: 全プロジェクトで共有する。
- バージョン切り替え: PATHを操作するだけで切り替えられる。
- venv: 組み込みのvenvで個別のバージョン指定とライブラリ環境を用意できる。
1.2 ツール
Python開発におけるツールの必要性
Part 1 > 1.1 手動でPythonを動かしてみる で見たように、Pythonランタイムの管理は自力でもできます。簡易的なスクリプトで済ませることも可能です。
しかし、実際の開発ではPythonランタイム1つで完結するわけではありません。
- リンター・フォーマッター
- テストランナー
- タスクランナー
- 配布パッケージ作成ツール
これらを組み合わせて使う必要があります。
また、複数人での開発(未来の自分や機械も含む)では以下が重要になります:
- 同じ状態を再現できること
- 作業ミスを防ぐこと
この結果、様々なツールが生まれてきました。
ソフトウェアツールの進化
ほとんどのツールは無から生まれるわけではありません。
新しいツールは「可能だがやるメリットがない操作」や「やってはいけないこと」、いわゆる地雷を踏まないような設定がデフォルトになっています。または不可能になっています。 また、時間とともにツールの扱うデータ量が大きくなっていくため、処理の効率化も求められます。
こうして現れる新しいツールには、以下のような特徴があります
- 統合: 様々なツール・機能をパッケージする
- 標準化: ベストプラクティスを標準とするように構成する
- 制約: アンチパターンや危険な操作を制限する
- 高速化: 処理時間・容量効率を改善する
この形で現れた新しいツールは、実現したいことが既存のツールでも頑張れば可能であったかもしれない、という認識を持たなければなりません。
何をどの程度楽にしてくれるのかを見るべきですね。78
この進化の中で縛りを加えられることが常なので、見返りに何を享受できるのかを見定めなくてはなりません。910
試行錯誤と進化の過程として整理するとこうなります。
- 最小限のパッケージがまず登場し、それを使うための付随ツールが生まれます。
- やがて運用の作法やベストプラクティス、そしてアンチパターンが出そろってきます。
- こうして手法とツールが収束していくため、最終的にそれらを統合したソリューションが出てくるわけです。
1.3 先に知っておいた方がいいもの
これらの基礎知識があると、これから紹介するツールがどのように設計されているかが理解しやすくなります。
PEP (Python Enhancement Proposal)
Pythonの機能追加や仕様変更を提案・議論するための文書です。
新しい言語機能、標準ライブラリの追加、開発プロセスの改善など、Pythonに関わる重要な変更はすべてPEPとして提案されます。
PEPには番号が振られ、議論を経て承認されると正式な仕様になります。
PEP一覧: https://peps.python.org/
PEP 517/518/621 と pyproject.toml
従来、Python配布パッケージの設定はsetup.pyに書かれていました。
また、プロジェクト設定やそのためのツールごとに異なるファイルが使用されていました。
PEP 517/518/621はこの状況を改善するために提案されました。
PEP 517: ビルドシステムのインターフェースを標準化する
PEP 518: ビルドに必要な依存関係をpyproject.tomlで宣言する
PEP 621: プロジェクトのメタデータをpyproject.tomlで統一的に記述する
pyproject.tomlはプロジェクトのメタデータや設定を集約するファイルです。 今では多くのツールが設定をpyproject.tomlに書けるようになっています。11
ビルドシステム
Pythonパッケージを配布可能な形式(wheelやsdist)にするための仕組みです。
setuptoolsなどはビルドを行うバックエンドです。
pyproject.tomlの[build-system]セクションで、どのビルドバックエンドを使うか指定します。
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
PyPA (Python Packaging Authority)
Pythonのパッケージングに関する標準を策定・維持している組織です。
PyPAが定めた仕様に従うことで、異なるツール間でも互換性が保たれます。
pipやsetuptoolsなどの基本ツールもPyPAの仕様に基づいています。
公式ドキュメント: https://packaging.python.org/ja/latest/
Python Standalone Builds
Python公式ではWindowsとmacOSのバイナリがありますがそれ以外はソース配布です。
このプロジェクトはビルド済みPythonバイナリを配布しています。
依存ライブラリを必要とせず展開してそのまま使用できることを目的としています。
OS・CPUアーキテクチャ・Linuxの場合はlibc、に合わせたビルド済みバイナリがあります。
Part 1 > 1.1 手動でPythonを動かしてみる でやったように手動でビルドすると
- ビルドに時間がかかる
- ビルドのためにクライアントに依存ライブラリをインストールする必要がある
- 異なる環境の場合
- 依存ライブラリのバージョンが異なる
- ビルド時の設定が異なる
などに注意しなければならないため、これを解消するためにビルド済みバイナリを使用します。
このプロジェクトは、はじめは個人プロジェクトでしたが、現在はuvの開発元であるAstralに移管されました。
Rye, uv, mise がこのビルド済みバイナリを使用しているので、事実上の標準になっています。
実はuv以外を使っていてもAstralの影響下にあるということです。
1.4 ツール比較一覧(令和最新版)
機能別のツールの対応範囲一覧表です。
※ 横スクロールあり
基本ツール
| 機能 | venv | pip | pip-tools | setuptools | twine | 備考 |
|---|---|---|---|---|---|---|
| 🐍 Python バージョン管理 | Part2 | |||||
| バージョン管理・インストール | ❌ | ❌ | ❌ | ❌ | ❌ | |
| 非Pythonバージョン管理 | ❌ | ❌ | ❌ | ❌ | ❌ | |
| 🌎 仮想環境 | Part3 | |||||
| 仮想環境管理 | ✅ | ❌ | ❌ | ❌ | ❌ | |
| 📦 パッケージ管理 | Part4 | |||||
| パッケージインストール | ❌ | ✅ | ✅ | ❌ | ❌ | |
| ロックファイル生成 | ❌ | ❌ | ✅ | ❌ | ❌ | |
| dev/prod分離 | ❌ | ▲ | ✅ | ❌ | ❌ | |
| 📤 パッケージング・配布 | Part5 | |||||
| wheel/sdist作成 | ❌ | ❌ | ❌ | ✅ | ❌ | |
| PyPI公開 | ❌ | ❌ | ❌ | ❌ | ✅ | |
| ⚙️ その他機能 | Part6 | |||||
| タスクランナー | ❌ | ❌ | ❌ | ❌ | ❌ | |
| 設定ファイル | pyvenv.cfg | requirements.txt | requirements.in | setup.py/setup.cfg | .pypirc |
対角行列のように左上から右下へと✅が続いています。
基本的な機能を提供するツールを組み合わせて使うことがわかります。
モダンツール群
| 機能 | pyenv | Pipenv | Poetry | Rye | uv | anaconda | 備考 |
|---|---|---|---|---|---|---|---|
| 🐍 Python バージョン管理 | Part2 | ||||||
| バージョン管理・インストール | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | |
| 非Pythonバージョン管理 | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | |
| 🌎 仮想環境 | Part3 | ||||||
| 仮想環境管理 | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | |
| 📦 パッケージ管理 | Part4 | ||||||
| パッケージインストール | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | |
| ロックファイル生成 | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | |
| dev/prod分離 | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | |
| 📤 パッケージング・配布 | Part5 | ||||||
| wheel/sdist作成 | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | |
| PyPI公開 | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | |
| ⚙️ その他機能 | Part6 | ||||||
| タスクランナー | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | |
| 設定ファイル | .python-version | Pipfile | pyproject.toml | pyproject.toml | pyproject.toml | environment.yml |
pyenvがバージョン管理専用ですね。
仮想環境とパッケージ管理を強化したのがPipenvです。
仮想環境・パッケージ管理にパッケージ配布も統合したPoetryがあります。
そして、オールインワンツールのrye/uvへと繋がっていきます。
Anaconda は別系統です。
数値計算や機械学習のためにコンピューターを使って計算をするがコンピューターに詳しいわけではなく、セットアップに付随するさまざなことに悩まされたくないユーザー向けに必要なものをPython言語環境以外も含めて揃えたAnaconda社のメンテナンスするディストリビューションです。
以降はこの表の補足なのでこれだけ見て帰ってもいいです。
Part 2: 🐍 Pythonバージョン管理
複数のPythonバージョンをインストールして切り替えるツールです。
基本的に Part 1 でやっていたビルド、パス設定を自動化してくれるものです。
2.1 比較
| ツール | インストール方法 | Python以外の管理 | 設定ファイル | 特徴 |
|---|---|---|---|---|
| システム | apt/dnf/brew等 | ✅ | - | OS標準 |
| pyenv | ソースビルド | ❌ | .python-version | Python専用 |
| Rye | バイナリ | ❌ | pyproject.toml | 統合ツール |
| uv | バイナリ | ❌ | pyproject.toml | 高速 |
| Anaconda | バイナリ | ✅ | environment.yml | 科学計算向け12 |
| asdf/mise | 様々 | ✅ | .tool-versions | 汎用ツール |
システムPython はaptやdnfでインストールするPythonのことです。ディストリビューションが提供するバージョンのため、最新ではないことが多いです。
pyenv は伝統と信頼のあるPython専用バージョン切り替えツールです。
Rye はPythonバージョン管理からパッケージ配布まで統合したオールインワンツールです。
uv は統合かつ高速なオールインワンツールです。
Anaconda はPythonも含めた様々なソフトをまとめてインストールできるツールです。アプリケーション開発よりも研究用途が主です。
asdf/mise は Python 以外のプログラミング言語ランタイムなどのバージョンを管理するツールです。
2.2 システムPython
Linuxディストリビューションをインストールしたら最初から存在するか、後から簡単なコマンドでpythonまたはpython3と名のついたパッケージをインストールできます。
複数バージョンのインストール
複数のPythonバージョンをインストールし、update-alternativesで管理する例です。
Ubuntu向けにPythonの様々なバージョンビルドを配布しているリポジトリの deadsnakes/ppa を使います。
root@x:/# apt update
root@x:/# apt install -y python3.12
root@x:/# apt install -y software-properties-common
root@x:/# add-apt-repository ppa:deadsnakes/ppa
root@x:/# apt install -y python3.13
インストール直後はpython3コマンドはシステムのデフォルトバージョンを指します。
root@x:/# python3 --version
Python 3.12.3
root@x:/# update-alternatives --display python3
update-alternatives: error: no alternatives for python3
update-alternativesにPythonのバージョンを登録します。
最後の数字は優先度で、大きい方が自動モードで選択されます。
root@x:/# update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 1
update-alternatives: using /usr/bin/python3.12 to provide /usr/bin/python3 (python3) in auto mode
root@x:/# update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.13 2
update-alternatives: using /usr/bin/python3.13 to provide /usr/bin/python3 (python3) in auto mode
優先度の高い3.13が自動的に選択されます。
root@x:/# python3 --version
Python 3.13.1
root@x:/# update-alternatives --display python3
python3 - auto mode
link best version is /usr/bin/python3.13
link currently points to /usr/bin/python3.13
link python3 is /usr/bin/python3
/usr/bin/python3.12 - priority 1
/usr/bin/python3.13 - priority 2
update-alternatives --configで対話的にバージョンを切り替えられます。
update-alternativesは /usr/bin/python3 へのシンボリックリンクの向き先を変えているだけです。
root@x:/# update-alternatives --config python3
There are 2 choices for the alternative python3 (providing /usr/bin/python3).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/bin/python3.13 2 auto mode
1 /usr/bin/python3.12 1 manual mode
2 /usr/bin/python3.13 2 manual mode
Press <enter> to keep the current choice[*], or type selection number: 1
update-alternatives: using /usr/bin/python3.12 to provide /usr/bin/python3 (python3) in manual mode
root@x:/# python3 --version
Python 3.12.3
EXTERNALLY-MANAGED
Python 3.11以降、システムPythonへの直接的なパッケージインストールが制限されるようになりました。
https://peps.python.org/pep-0668/
https://packaging.python.org/ja/latest/specifications/externally-managed-environments/
これはPEP 668で定義された「外部管理環境(Externally Managed Environments)」の仕組みによるものです。
Ubuntu 24.04 (noble) でシステムPythonに対して pip install を実行すると、以下のようなエラーが表示されます。
root@x:/# apt update; apt install -y python3 python3-pip
root@x:/# pip3 install invoke
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
sure you have python3-full installed.
If you wish to install a non-Debian packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.
See /usr/share/doc/python3.12/README.venv for more information.
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
一般ユーザーでpipに--userを使っても同様です。
Ubuntu 22.04 (jammy) では制限は適用されていませんでした。
システムのパッケージマネージャー(apt等)とpipが同じ場所にパッケージをインストールすると、依存関係の競合やシステムの破壊が起きる可能性があります。
PEP 668はこれを防ぐため、システムPython環境への直接的なpipインストールを制限しました。
--break-system-packages フラグを使えばインストール自体は可能ですが警告のとおりトラブルにつながる可能性があります。
pyenvなどでシステムとは別のPythonランタイムを用意するか、venvやvirtualenvなどの仮想環境を使うことが推奨されます。
配置
これはUbuntuの例です。
バージョン付きの各バージョンのPythonランタイムとバージョン無しで使用するシンボリックリンクがあります。
/usr/
├── bin/
│ ├── python3 -> python3.12 ← update-alternatives により指定する
│ ├── python3.11
│ └── python3.12
└── lib/
├── python3.11/
└── python3.12/
まとめ
システムPythonは導入と実行が手軽です。
ただし、Pythonバージョンはディストリビューションが指定するもので選択の自由がなく、パッケージインストールにも制約があります。
このため、pyenvなどのツールがあります。
2.3. pyenv
https://github.com/pyenv/pyenv
pyenvはPython専用のバージョン管理ツールです。
全体のglobalまたはディレクトリ単位のlocalとしてバージョンを切り替えます。
バージョン管理のみなので、開発作業としては後発のバージョン管理以外の機能を持つツールと組み合わせるか、あるいは出番がありません。
他の言語やツールのバージョン管理もしたいときは asdf/mise も選択肢になります。
Part 1で手動で行った「ビルド→PATH設定」を自動化します。
仕組み
セットアップ例
## コンテナ起動
$ docker run -it --rm --hostname "x" ubuntu:noble bash
## curl, git, ライブラリインストール
root@x:/# apt update; apt install -y curl git;
## ubuntuユーザーへ切り替え
root@x:/# su - ubuntu
ubuntu@x:~$ pwd
/home/ubuntu
## pyenv インストール
ubuntu@x:~$ curl https://pyenv.run | bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 270 100 270 0 0 3537 0 --:--:-- --:--:-- --:--:-- 3552
Cloning into '/home/ubuntu/.pyenv'...
WARNING: seems you still have not added 'pyenv' to the load path.
# Load pyenv automatically by appending
# the following to
# ~/.bash_profile if it exists, otherwise ~/.profile (for login shells)
# and ~/.bashrc (for interactive shells) :
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"
# Restart your shell for the changes to take effect.
# Load pyenv-virtualenv automatically by adding
# the following to ~/.bashrc:
eval "$(pyenv virtualenv-init -)"
## シェル環境変数登録
ubuntu@x:~$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
ubuntu@x:~$ echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
ubuntu@x:~$ echo 'eval "$(pyenv init - bash)"' >> ~/.bashrc
## 確認
ubuntu@x:~$ exec "$SHELL"
ubuntu@x:~$ pyenv --version
pyenv 2.6.16
インストールと有効化
## Python3.12をインストールします。
ubuntu@x:~$ pyenv install 3.12
Downloading Python-3.12.12.tar.xz...
-> https://www.python.org/ftp/python/3.12.12/Python-3.12.12.tar.xz
Installing Python-3.12.12...
Installed Python-3.12.12 to /home/ubuntu/.pyenv/versions/3.12.12
## globalで使います
ubuntu@x:~$ pyenv global 3.12
ubuntu@x:~$ pyenv versions
* 3.12.12 (set by /home/ubuntu/.pyenv/version)
ubuntu@x:~/project$ cat ~/.pyenv/version
3.12
ubuntu@x:~$ which python
/home/ubuntu/.pyenv/shims/python
ubuntu@x:~$ python --version
Python 3.12.12
## projectディレクトリは3.13を使います
### ディレクトリ作成
ubuntu@x:~$ mkdir project
ubuntu@x:~$ cd project/
### インストールされてない場合は警告が出ます
ubuntu@x:~/project$ pyenv local 3.13
pyenv: version `3.13' not installed
ubuntu@x:~/project$ pyenv install 3.13
Downloading Python-3.13.11.tar.xz...
-> https://www.python.org/ftp/python/3.13.11/Python-3.13.11.tar.xz
Installing Python-3.13.11...
Installed Python-3.13.11 to /home/ubuntu/.pyenv/versions/3.13.11
### localで3.13を指定
ubuntu@x:~/project$ pyenv local 3.13
ubuntu@x:~/project$ cat .python-version
3.13
ubuntu@x:~/project$ which python
/home/ubuntu/.pyenv/shims/python
ubuntu@x:~/project$ python --version
Python 3.13.11
pyenvの肝はshimsという仕組みです。
pythonを探します。
ubuntu@x:~/project$ echo $PATH
/home/ubuntu/.pyenv/shims:/home/ubuntu/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
ubuntu@x:~/project$ which python
/home/ubuntu/.pyenv/shims/python
## 実態はシェルスクリプトです
ubuntu@x:~/project$ cat /home/ubuntu/.pyenv/shims/python
#!/usr/bin/env bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x
program="${0##*/}"
export PYENV_ROOT="/home/ubuntu/.pyenv"
exec "/home/ubuntu/.pyenv/libexec/pyenv" exec "$program" "$@"
pythonコマンドは実際にはpyenvスクリプトを実行しており、pyenvが以下の優先順で設定を探します:
PYENV_VERSION環境変数- カレントディレクトリの
.python-version - 親ディレクトリを遡って
.python-versionを探す - グローバル設定 (
~/.pyenv/version)
ディレクトリ構成
通常のインストール方法では$HOME/.pyenvにスクリプトとランタイムがあります。
$HOME/
├── .pyenv/
│ ├── shims/ # PATH環境変数の先頭に追加
│ │ ├── python -> pyenv
│ │ └── pip -> pyenv
│ ├── versions/ # ビルド済みPython
│ │ ├── 3.12.12/
│ │ │ ├── bin/python3.12
│ │ │ └── lib/python3.12/
│ │ └── 3.13.11/
│ │ ├── bin/python3.13
│ │ └── lib/python3.13/
│ └── version # グローバル設定
├── project/
│ └── .python-version # ローカル設定 (3.13)
まとめ
pyenvはPart 1で手で行ったのと同様にソースからビルドします。
そのため、依存ライブラリのインストールが必要でビルド時間がかかります。
切り替えはシェルにshimsへのパスを設定し、shimsが.python-versionなどを見て実行します。
2.4 Rye
pipenvとpoetryがバージョン管理を対象としなかったのに対して、ryeがすべてを管理することができるツールとして現れました。
本体の実装はRustですが、内部的にパッケージインストールにはpip/pip-tools (のちにuv) を、パッケージ配布にはtwineを使うなど既存ツールの呼び出しラッパーの部分も多いです。
野心的にリプレースするのではなく実用に振っているというところでしょうか。
仕組み
セットアップ例
## コンテナ起動
$ docker run -it --rm --hostname "x" ubuntu:noble bash
## curlインストール
root@x:/# apt update; apt install -y curl ;
## ubuntuユーザーへ切り替え
root@x:/# su - ubuntu
ubuntu@x:~$ pwd
/home/ubuntu
## Ryeインストール
ubuntu@x:~$ curl -sSf https://rye.astral.sh/get | bash
This script will automatically download and install rye (latest) for you.
######################################################################## 100.0%
Welcome to Rye!
This installer will install rye to /home/ubuntu/.rye
This path can be changed by exporting the RYE_HOME environment variable.
Details:
Rye Version: 0.44.0
Platform: linux (x86_64)
✔ Continue? · yes
✔ What should running `python` or `python3` do when you are not inside a Rye managed project? · Run a Python installed and managed by Rye
✔ Which version of Python should be used as default toolchain? · cpython@3.12
Installed binary to /home/ubuntu/.rye/shims/rye
Bootstrapping rye internals
Fetching requested internal toolchain 'cpython@3.12.9'
Downloading cpython@3.12.9
Checking checksum
Unpacking
Downloaded cpython@3.12.9
Updated self-python installation at /home/ubuntu/.rye/self
The rye directory /home/ubuntu/.rye/shims was not detected on PATH.
It is highly recommended that you add it.
✔ Should the installer add Rye to PATH via .profile? · yes
Added to PATH.
note: for this to take effect you will need to restart your shell or run this manually:
source "$HOME/.rye/env"
For more information read https://rye.astral.sh/guide/installation/
All done!
ubuntu@x:~$ source "$HOME/.rye/env"
ubuntu@x:~$ rye --version
rye 0.44.0
commit: 0.44.0 (e21393834 2025-02-26)
platform: linux (x86_64)
self-python: cpython@3.12.9
symlink support: true
uv enabled: true
インストール時にプロジェクトの外で実行するPythonとしてRyeの管理するものを使うと選択しました。
? What should running `python` or `python3` do when you are not inside a Rye managed project? ›
❯ Run a Python installed and managed by Rye
Run the old default Python (provided by your OS, pyenv, etc.)
これは後からでも有効にできます。
$ rye config --set-bool behavior.global-python=true
$ rye config --get behavior.global-python
true
.rye/config に設定があります。
ubuntu@x:~$ rye config --get behavior.global-python
true
ubuntu@x:~$ ry ocnfig --show-path
-bash: ry: command not found
ubuntu@x:~$ rye config --show-path
/home/ubuntu/.rye/config.toml
ubuntu@x:~$ cat .rye/config.toml
[behavior]
global-python = true
[default]
toolchain = "cpython@3.12"
shimsを通してPythonが実行されています。
ubuntu@x:~$ which python
/home/ubuntu/.rye/shims/python
ubuntu@x:~$ python --version
Python 3.12.9
バージョンを変える例
ubuntu@x:~$ rye config --set default.toolchain="cpython@3.13"
ubuntu@x:~$ cat .rye/config.toml
[behavior]
global-python = true
[default]
toolchain = "cpython@3.13"
## Pythonのダウンロードが必要です。
ubuntu@x:~$ rye fetch
Downloading cpython@3.13.2
Checking checksum
Unpacking
Downloaded cpython@3.13.2
ubuntu@x:~$ python --version
Python 3.13.2
ディレクトリ構成
$HOME/.rye にインストールされます。
$HOME/
├── .rye/
│ ├── shims/
│ │ ├── python (hardlink)
│ │ ├── python3 (hardlink)
│ │ └── rye (hardlink)
│ └── py/
│ ├── cpython@3.12.9/
│ │ ├── bin/
│ │ ├── python -> python3.12
│ │ ├── python3 -> python3.12
│ │ └── python3.12
│ └── cpython@3.13.2/
.rye/shims/ の下は同じバイナリです。呼び出され方で動作を切り替えています。
pyenvのshimsはシェルスクリプトでしたが、Ryeのshimsはバイナリです。
動作は次のようになります。
- プロジェクト内で python を呼ぶ
- shims/ の python が呼ばれる (shims)
- 設定に基づいてRyeの管理するPythonを使用するか決定する
まとめ
Ryeはバージョン管理も含めたPython開発環境です。
Pythonバイナリはビルド済みのものを環境に合わせてダウンロードします。
2.5 uv
uvは2025年現在最高のPython管理ツールと呼ばれています。※ X(Twitter)調べ
はじめはパッケージの依存解決が高速な仮想環境管理ツールでした。
https://github.com/astral-sh/uv/tree/0.0.5
An extremely fast Python package installer and resolver, written in Rust. Designed as a drop-in replacement for pip and pip-compile.
⚖️ Drop-in replacement for common pip, pip-tools, and virtualenv commands. ⚡️ 10-100x faster than pip and pip-tools (pip-compile and pip-sync).
やがてPythonプロジェクト管理ツールとして機能が追加されRyeと同様にオールインワンツールとなり、Ryeの後継プロジェクトに位置しています。
https://github.com/astral-sh/uv/tree/0.3.0
An extremely fast Python package and project manager, written in Rust.
🚀 A single tool to replace pip, pip-tools, pipx, poetry, pyenv, virtualenv, and more.
Ryeと異なりほとんどの機能をRustで実装しています。
仕組み
セットアップ例
## コンテナ起動
$ docker run -it --rm --hostname "x" ubuntu:noble bash
## curlインストール
root@x:/# apt update; apt install -y curl;
## ubuntuユーザーへ切り替え
root@x:/# su - ubuntu
ubuntu@x:~$ pwd
/home/ubuntu
## uvインストール
ubuntu@x:~$ curl -LsSf https://astral.sh/uv/install.sh | sh
downloading uv 0.9.17 x86_64-unknown-linux-gnu
no checksums to verify
installing to /home/ubuntu/.local/bin
uv
uvx
everything's installed!
To add $HOME/.local/bin to your PATH, either restart your shell or run:
source $HOME/.local/bin/env (sh, bash, zsh)
source $HOME/.local/bin/env.fish (fish)
ubuntu@x:~$ source $HOME/.local/bin/env
ubuntu@x:~$ uv --version
uv 0.9.17
Pythonをインストールします。
## Python3.12インストール
ubuntu@x:~$ uv python install 3.12
## 自動でバージョン付きのコマンドまたは uv run python で使える
ubuntu@x:~$ python3.12 --version
Python 3.12.12
ubuntu@x:~$ uv run python --version
Python 3.12.12
ubuntu@x:~$ which python3.12
/home/ubuntu/.local/bin/python3.12
ubuntu@x:~$ uv python list
...
cpython-3.12.12-linux-x86_64-gnu .local/bin/python3.12 -> .local/share/uv/python/cpython-3.12.12-linux-x86_64-gnu/bin/python3.12
cpython-3.12.12-linux-x86_64-gnu .local/share/uv/python/cpython-3.12.12-linux-x86_64-gnu/bin/python3.12
...
## シェルのpython, python3をuvのものにする
ubuntu@x:~$ uv python install 3.12 --default
warning: The `--default` option is experimental and may change without warning. Pass `--preview-features python-install-default` to disable this warning
ubuntu@x:~$ python --version
Python 3.12.12
ubuntu@x:~$ which python3
/home/ubuntu/.local/bin/python3
ubuntu@x:~$ ls -alt $(which python3)
lrwxrwxrwx 1 ubuntu ubuntu 83 Dec 15 12:18 /home/ubuntu/.local/bin/python3 -> /home/ubuntu/.local/share/uv/python/cpython-3.12.12-linux-x86_64-gnu/bin/python3.12
Pythonのインストールは Python Standalone Builds を使用するので速いです。
自動でバージョン付きのpythonコマンドがパスに置かれます。(便利)
uv python install VERSION --default は experimental ですが、これで python, python3 コマンドが uv 管理下のものになります。
ディレクトリ構成
$HOME/.local/bin/ にパスを通して、そこから $HOME/.local/share/uv 以下にインストールされたPythonを使っています。
$HOME/.local/
├─ bin/
│ ├── python (シンボリックリンク)
│ ├── python3 (シンボリックリンク)
│ ├── python3.12 (シンボリックリンク)
│ ├── python3.13 (シンボリックリンク)
│ ├── env
│ ├── uv
│ └── uvx
│
├── share/uv/
│ └── python/
│ ├── cpython-3.12.12-linux-x86_64-gnu/
│ │ ├── bin/python3
│ │ └── lib/
│ └── cpython-3.13.11-linux-x86_64-gn/
│ ├── bin/python3
│ └── lib/
まとめ
pipの高速な代替からはじまり、今ではPython開発環境全体を管理するようになったuvです。
2.6 Anaconda
https://www.anaconda.com/download
科学計算エコシステム全体を管理するツールで、Pythonだけでなく他言語やIDE、JupyterNotebookもセットになっています。PyPIとは別の独自リポジトリを持ち、バイナリ配布でC/C++ライブラリも管理できます。 現在はPyPIでもビルド済みライブラリに困ることは少なくなり、商用利用ライセンスの導入もあるため、個人や小規模では強く選ぶ理由は少なくなっています。
2.7 asdf / mise
https://asdf-vm.com / https://mise.jdx.dev
汎用的な言語バージョン管理ツールです。
asdfとmiseは、Python、Node.js、Ruby、Go、Terraformなど様々な言語・ツールを統一的に管理します。
Pythonのpyenvのほかに、Node.jsにはnodenv、Rubyにはrbenv、など言語ごとに色んなツールが{言語名}envの名前に限らず乱立していたのをまとめています。
仕組み
asdfは各言語ごとにプラグインを追加します。
$ asdf plugin add python
$ asdf plugin add nodejs
$ asdf install python 3.11.10
$ asdf install nodejs 20.11.0
コマンド自体はフロントエンドとして操作とシェルを管理して、具体的なインストールはプラグインで行うということですね。
$ cd ~/app07
$ asdf local python 3.11.10
$ asdf local nodejs 20.11.0
$ cat .tool-versions
python 3.11.10
nodejs 20.11.0
.tool-versionsで複数の言語を一元管理できます。
ディレクトリ構成
$HOME/
├── .asdf/
│ ├── installs/
│ │ ├── python/
│ │ │ ├── 3.11.10/
│ │ │ └── 3.12.7/
│ │ └── nodejs/
│ │ └── 20.11.0/
│ └── shims/
│ ├── python
│ └── node
└── project/
└── .tool-versions
mise
miseはasdfの高速な代替品で互換性があります。
https://mise.jdx.dev/dev-tools/comparison-to-asdf.html
asdfは当初シェルスクリプトによる実装でした。
miseはRust実装で高速化をしました。
asdfはGo言語で再実装されました。
miseは設定ファイルとして .tool-versions または mise.toml を使います。
Pythonについて
asdf (https://github.com/asdf-community/asdf-python) はpyenvを使います。 mise (built-in) は Python Standard Build のビルド済みバイナリを使用します。
2.8 まとめ
何かを作るときPythonのみで完結しないことも多いので、その時は導入を考えるのはいかがでしょうか。
Part 3: 🌎📦 仮想環境とパッケージ管理
Part 1で学んだように、venvを使うとプロジェクトごとに独立したパッケージ環境を作れます。
また、pip installでパッケージをインストールし、グローバル環境と仮想環境の違いを学びました。
このPartでは、仮想環境管理とパッケージ管理を担う様々なツールを比較します。
これら2つの機能は密接に関連しているため、一緒に扱います。
3.1 比較
仮想環境管理
| ツール | 有効化方式 | 環境の配置 | 設定ファイル | 特徴 |
|---|---|---|---|---|
| venv | 手動activate | 基本的にプロジェクト内に配置する | pyvenv.cfg | Python標準 |
| Pipenv | サブシェル起動 | ユーザーディレクトリ | Pipfile | 自動環境切替 |
| Poetry | コマンド経由 | ユーザーディレクトリ プロジェクトディレクトリ | pyproject.toml | 透過的管理 |
| Rye | コマンド経由 | プロジェクト内 | pyproject.toml | 統合 |
| uv | コマンド経由 | プロジェクト内 | pyproject.toml | 高速・統合 |
| Anaconda | activate切替 | 専用ディレクトリ | environment.yml | 環境中心設計 |
パッケージ管理
| ツール | ロックファイル | dev/prod分離 |
|---|---|---|
| pip | ❌ | ファイル分割 or pyproject.toml |
| pip-tools | ✅ | ファイル分割 or pyproject.toml |
| Pipenv | ✅ | ✅ |
| Poetry | ✅ | ✅ |
| Rye | ✅ | ✅ |
| uv | ✅ | ✅ |
| Anaconda | ✅ | ✅ |
おおまかな解説
- venv + pip: Python標準の最小限の仕組みです。
- pip-tools: pipを拡張して依存関係管理を強化します。
- Pipenv: 仮想環境とパッケージ管理を統合したツールです。
- Poetry: 仮想環境、パッケージ管理、パッケージ配布を統合したツールです。
- Rye: Pythonバージョン管理から仮想環境、パッケージ管理、配布までまとめたオールインワンのツールです。
- uv: パッケージ管理の高速化を実現し、さらにPython環境、パッケージ管理、配布まで含めたオールインワンツールです。
- Anaconda: Python以外の言語環境も含めた科学計算環境を管理します。
Part 1で学んだsource .venv/bin/activateという基礎を理解していれば、各ツールがこの作業をどう扱うかが見えてきます。
3.2 venv + pip
Python標準のツールです。
venvはPython 3.3から標準ライブラリに含まれる仮想環境作成ツールです。 pipはPython標準のパッケージインストーラーです。 Part 1で使ったものです。
仮想環境管理
$ cd ~/app08
$ python3 -m venv .venv ← このとき仮想環境で使うPythonバージョン(バイナリ)が決定する
$ source .venv/bin/activate ← 作業しているシェルで指定Python環境を指し示すように環境変数を設定する
(.venv) $ python --version
Python 3.11.0
(.venv) $ deactivate
$
ディレクトリ構成
$HOME/
└── app08/
├── .venv/
│ ├── bin/
│ │ ├── python3 -> /opt/python-3.11.0/bin/python3 # シンボリックリンク
│ │ ├── pip3
│ │ └── activate # 有効化スクリプト
│ ├── lib/
│ │ └── python3.11/
│ │ └── site-packages/ # プロジェクト専用パッケージ
│ └── pyvenv.cfg # 設定ファイル
└── main.py
pyvenv.cfgには元のPythonへのパスなどが記録されています:
home = /opt/python-3.11.0/bin
include-system-site-packages = false
version = 3.11.0
virtualenv との関係
virtualenvは、venvの前身となったサードパーティツールです。
Python 2時代から存在し、Python 3.3で一部の仕様がvenvとして標準化されました。
現在でもvirtualenvは開発が続いており、venvより高速で機能が豊富です。
パッケージ管理
Pythonユーザーにはなじみ深い pip install でパッケージインストールをします。
(.venv) $ pip install requests
Collecting requests
Downloading requests-2.32.5-py3-none-any.whl (64 kB)
Collecting certifi>=2017.4.17
Downloading certifi-2025.11.12-py3-none-any.whl (164 kB)
...
Successfully installed certifi-2025.11.12 charset-normalizer-3.4.4 idna-3.11 requests-2.32.5 urllib3-2.5.0
実行してインストールする。非常にシンプルです。
バージョン管理
requirements.txt
パッケージを書いたテキストファイルです。
requirements.txt
flask
numpy>=2.3.0
requests==2.32.5
バージョンの指定もできます。
pip install -r でファイルからインストールします。
(.venv) $ pip install -r requirements.txt
これを手動でメンテナンスするのは面倒です。
pip freeze
インストール済みパッケージをファイルに記録:
(.venv) $ pip freeze > requirements.txt
(.venv) $ cat requirements.txt
certifi==2025.11.12
charset-normalizer==3.4.4
idna==3.11
requests==2.32.5
urllib3==2.5.0
この pip freeze はその環境にあるすべてを記録するため、使い勝手が悪いという問題があります。
不要なものがあれば手動で整理しなければなりません。
依存関係解決
https://pip.pypa.io/en/stable/user_guide/#changes-to-the-pip-dependency-resolver-in-20-3-2020
pip 20.3で依存解決の問題が解消されました。
以前は順番にそのパッケージのことだけを考慮してパッケージをインストールするため、パッケージ間で互換性のない状態になりえました。
例:
virtualenv==20.0.2 が six>=1.12.0,<2 (1.12以上2未満) を要求しながら
pip install "six<1.12" "virtualenv==20.0.2" が成功してしまいます。
新しい依存解決は互換性のないバージョンの組み合わせを検出して拒否するようになりました。
ただし、この依存解決処理のために遅くなっています。
pyproject.toml
Python3.11のpipからPEP 518のpyproject.tomlのdependencyに対応しています。
pyproject.toml
[project]
name = "myapp"
version = "0.1.0"
dependencies = [
"flask>=3.0.0",
"requests>=2.28.0",
]
pip install . でdependenciesがインストールされます。
(.venv) ubuntu@x:~/pyproj$ ls
pyproject.toml
(.venv) ubuntu@x:~/pyproj$ pip install -e .
(.venv) ubuntu@x:~/pyproject$ pip freeze
blinker==1.9.0
certifi==2025.11.12
charset-normalizer==3.4.4
click==8.3.1
Flask==3.1.2
idna==3.11
iniconfig==2.3.0
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.3
# Editable install with no version control (myapp==0.1.0)
-e /home/ubuntu/pyproject
packaging==25.0
pluggy==1.6.0
Pygments==2.19.2
pytest==9.0.2
requests==2.32.5
urllib3==2.6.2
Werkzeug==3.1.4
## 何かが増えている
(.venv) ubuntu@x:~/pyproject$ ls
myapp.egg-info pyproject.toml
-eを入れないと、自分自身もパッケージの一つになってしまいます。
pyproject.tomlの提案経緯から、どちらかというと自身がライブラリとして利用されるための環境設定の面が強いので、単体のアプリケーション開発だとしっくりこない気もします。
dev/prod分離 pyproject.toml
本番リリースに含めるライブラリに加えて、開発のときはテストツールなどを入れることがあります。
project.optional-dependencies で追加のパッケージのグループを設定できます。
pyproject.toml
[project]
name = "myapp"
version = "0.1.0"
dependencies = [
"flask>=3.0.0",
"requests>=2.28.0",
]
[project.optional-dependencies]
dev = [
"pytest (>=9.0.2,<10.0.0)"
]
~
(.venv) ubuntu@x:~/pyproj$ pip install -e .[dev]
(.venv) ubuntu@x:~/pyproj$ pip freeze
... 省略
pytest==9.0.2
... 省略
まとめ
pipはPython標準で使いやすく改良もされていますが、パッケージが多いと遅さが目立ちます。
3.3 pip-tools
https://github.com/jazzband/pip-tools/
pip-toolsは、pipを拡張して依存関係の自動解決とロックファイル生成を提供します。
依存関係ロック
requirements.inに抽象的な依存関係を書き、pip-compileで具体的なrequirements.txtを生成します。
requirements.in
要件として使うパッケージをrequirements.inに書きます。
requirements.in
scipy
具体的なパッケージバージョンを指定したrequirements.txtを生成します。
(.venv) ubuntu@x:~/project$ pip-compile requirements.in
WARNING: --strip-extras is becoming the default in version 8.0.0. To silence this warning, either use --strip-extras to opt into the new default or use --no-strip-extras to retain the existing behavior.
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile requirements.in
#
numpy==2.3.5
# via scipy
scipy==1.16.3
# via -r requirements.in
dev/prod分離
本番リリースに含めるライブラリに加えて、開発のときはテストツールなどを入れることがあります。
requirements.inは他のファイルをインポートできます。
requirements-dev.in
-c requirements.txt # 本番環境の制約を継承
pytest
リリース用のライブラリを固定してから開発用のrequirements-dev.txtを生成します。
(.venv) $ pip-compile requirements.in -o requirements.txt
(.venv) $ pip-compile requirements-dev.in -o requirements-dev.txt
requirements-dev.txt
iniconfig==2.3.0
# via pytest
packaging==25.0
# via pytest
pluggy==1.6.0
# via pytest
pygments==2.19.2
# via pytest
pytest==9.0.2
# via -r requirements-dev.in
これがうれしい。
ハッシュ生成
改ざん検知・変更検知のためsdistやwheelパッケージへのハッシュ収集に対応しています。
(.venv) $ pip-compile --generate-hashes requirements.in
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --generate-hashes requirements.in
#
numpy==2.3.5 \
--hash=sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b \
--hash=sha256: ...省略
# via scipy
scipy==1.16.3 \
--hash=sha256:0151a0749efeaaab78711c78422d413c583b8cdd2011a3c1d6c794938ee9fdb2 \
--hash=sha256: ...省略
# via -r requirements.in
PyPIの場合は一度アップロードしたバージョンについてファイルの変更は禁止されているので改ざん検知のみ、プライベートリポジトリの場合は改ざんもしくは何かしらの変更があったかを検知する手段になります。
pip-sync
pip-sync は pip install -r requirements.txt と、requirements.txt に記載されていないものを除きます。
まとめ
pipのみでは難しかった依存関係管理を提供します。
3.4 Pipenv
https://pipenv-ja.readthedocs.io/ja/translate-ja/
これまで venv、pip、pip-tools で細かい手順やファイルを組み合わせてやりたいことを実現してきました。
Pipenvは、この仮想環境の作成・管理を自動化してくれるラッパーです。
仮想環境管理
セットアップ例
## コンテナ起動
$ docker run -it --rm --hostname "x" ubuntu:noble bash
## システムPythonとpipインストール
root@x:/# apt update; apt install -y curl python3-pip;
## ubuntuユーザーへ切り替え
root@x:/# su - ubuntu
ubuntu@x:~$ pwd
/home/ubuntu
## Pipenvインストール
## ※ システムPythonの制限を回避するために --break-system-packages を使っています。
## pyenvなどを使ってシステムPython以外の環境を使うことを推奨します。
ubuntu@x:~$ pip3 install --break-system-packages --user install pipenv
## --user を付けたので ~/.local/bin/ にコマンドがインストールされます。
## ここにPATHを通すか python3 -m で呼び出せます。
ubuntu@x:~$ ls ~/.local/bin/
pipenv pipenv-resolver virtualenv
ubuntu@x:~$ python3 -m pipenv --version
pipenv, version 2026.0.2
Pipenvは仮想環境をユーザーディレクトリに集中管理します。
venvでは任意の場所に作成していましたが、Pipenvが代わりにやってくれます。
ここでは pipenv のある /home/ubuntu/.local/bin/ にパスを通しているものとします。
ubuntu@x:~$ mkdir project
ubuntu@x:~$ cd project/
## 初回のpipenv実行でvenvと設定ファイルが作られプロジェクトになります
ubuntu@x:~/project$ python3 -m pipenv shell
Creating a virtualenv for this project
Pipfile: /home/ubuntu/project/Pipfile
Using /usr/bin/python33.12.3 to create virtualenv...
⠙ Creating virtual environment...created virtual environment CPython3.12.3.final.0-64 in 99ms
creator CPython3Posix(dest=/home/ubuntu/.local/share/virtualenvs/project-ipe16O64, clear=False, no_vcs_ignore=False,
global=False)
seeder FromAppData(download=False, pip=bundle, via=copy, app_data_dir=/home/ubuntu/.local/share/virtualenv)
added seed packages: pip==25.3
activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
✔ Successfully created virtual environment!
Virtualenv location: /home/ubuntu/.local/share/virtualenvs/project-ipe16O64
Creating a Pipfile for this project...
Launching subshell in virtual environment...
ubuntu@x:~/project$ source /home/ubuntu/.local/share/virtualenvs/project-ipe16O64/bin/activate
(project) ubuntu@x:~/project$ eval "_pipenv_old_deactivate() { $(declare -f deactivate | tail -n +2) }"; deactivate() { _pipenv_old_deactivate; unset PIPENV_ACTIVE; }
(project) ubuntu@x:~/project$
## 仮想環境が作成されています
(project) ubuntu@x:~/project$ which python3
/home/ubuntu/.local/share/virtualenvs/project-ipe16O64/bin/python3
(project) ubuntu@x:~/project$ ls
Pipfile
## シェルに入るとそのまま仮想環境の python3 を実行できますが、pipenvを通して行う操作が多いので入らなくてもいいです。
(project) ubuntu@x:~/project$ exit
exit
ubuntu@x:~/project$
Pipfileはプロジェクトの設定(メタ情報・依存パッケージ・環境)を記録するtomlファイルです。
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
[dev-packages]
[requires]
python_version = "3.12"
Pythonを使った開発では仮想環境を使う。これをツールとして示しています。
パッケージ管理
プロジェクト・ロックファイル
重要なのはPipfileとPipfile.lockです。
scipy をインストールします。
ubuntu@x:~/project$ pipenv install scipy
Pipfile.lock not found, creating...
Locking dependencies...
Locking dependencies...
Updated Pipfile.lock (702ad05de9bc9de99a4807c8dde1686f31e0041d7b5f6f6b74861195a52110f5)!
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Installing scipy...
✔ Installation Succeeded
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Installing dependencies from Pipfile.lock (2110f5)...
All dependencies are now up-to-date!
Upgrading scipy in dependencies.
Building requirements...
Resolving dependencies...
✔ Success!
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Installing dependencies from Pipfile.lock (f11941)...
All dependencies are now up-to-date!
Installing dependencies from Pipfile.lock (f11941)...
ubuntu@x:~/project$ pipenv graph
scipy==1.16.3
└── numpy [required: >=1.25.2,<2.6, installed: 2.3.5]
インストール後の Pipfile の packages に依存が追加されています。
[packages]
scipy = "*"
Pipfile.lock は何をインストールしたかを示すjsonファイルです。
{
"_meta": {
"hash": {
"sha256": "4b6ebafdeac340741f97745bef1ce3ea578bd2b2cb08b3e0ad370f99fbf11941"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.12"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"numpy": {
"hashes": [
"sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b",
(省略)
"sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520"
],
"markers": "python_version >= '3.11'",
"version": "==2.3.5"
},
"scipy": {
"hashes": [
"sha256:0151a0749efeaaab78711c78422d413c583b8cdd2011a3c1d6c794938ee9fdb2",
(省略)
"sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d"
],
"index": "pypi",
"markers": "python_version >= '3.11'",
"version": "==1.16.3"
}
},
"develop": {}
}
Pipfile.lock全文
{
"_meta": {
"hash": {
"sha256": "4b6ebafdeac340741f97745bef1ce3ea578bd2b2cb08b3e0ad370f99fbf11941"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.12"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"numpy": {
"hashes": [
"sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b",
"sha256:0472f11f6ec23a74a906a00b48a4dcf3849209696dff7c189714511268d103ae",
"sha256:04822c00b5fd0323c8166d66c701dc31b7fbd252c100acd708c48f763968d6a3",
"sha256:052e8c42e0c49d2575621c158934920524f6c5da05a1d3b9bab5d8e259e045f0",
"sha256:09a1bea522b25109bf8e6f3027bd810f7c1085c64a0c7ce050c1676ad0ba010b",
"sha256:0cd00b7b36e35398fa2d16af7b907b65304ef8bb4817a550e06e5012929830fa",
"sha256:0d8163f43acde9a73c2a33605353a4f1bc4798745a8b1d73183b28e5b435ae28",
"sha256:1062fde1dcf469571705945b0f221b73928f34a20c904ffb45db101907c3454e",
"sha256:11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017",
"sha256:17531366a2e3a9e30762c000f2c43a9aaa05728712e25c11ce1dbe700c53ad41",
"sha256:1978155dd49972084bd6ef388d66ab70f0c323ddee6f693d539376498720fb7e",
"sha256:1ed1ec893cff7040a02c8aa1c8611b94d395590d553f6b53629a4461dc7f7b63",
"sha256:2dcd0808a421a482a080f89859a18beb0b3d1e905b81e617a188bd80422d62e9",
"sha256:2e2eb32ddb9ccb817d620ac1d8dae7c3f641c1e5f55f531a33e8ab97960a75b8",
"sha256:2feae0d2c91d46e59fcd62784a3a83b3fb677fead592ce51b5a6fbb4f95965ff",
"sha256:3095bdb8dd297e5920b010e96134ed91d852d81d490e787beca7e35ae1d89cf7",
"sha256:30bc11310e8153ca664b14c5f1b73e94bd0503681fcf136a163de856f3a50139",
"sha256:3101e5177d114a593d79dd79658650fe28b5a0d8abeb8ce6f437c0e6df5be1a4",
"sha256:396084a36abdb603546b119d96528c2f6263921c50df3c8fd7cb28873a237748",
"sha256:3997b5b3c9a771e157f9aae01dd579ee35ad7109be18db0e85dbdbe1de06e952",
"sha256:414802f3b97f3c1eef41e530aaba3b3c1620649871d8cb38c6eaff034c2e16bd",
"sha256:51c1e14eb1e154ebd80e860722f9e6ed6ec89714ad2db2d3aa33c31d7c12179b",
"sha256:51c55fe3451421f3a6ef9a9c1439e82101c57a2c9eab9feb196a62b1a10b58ce",
"sha256:5ee6609ac3604fa7780e30a03e5e241a7956f8e2fcfe547d51e3afa5247ac47f",
"sha256:612a95a17655e213502f60cfb9bf9408efdc9eb1d5f50535cc6eb365d11b42b5",
"sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42",
"sha256:63c0e9e7eea69588479ebf4a8a270d5ac22763cc5854e9a7eae952a3908103f7",
"sha256:66f85ce62c70b843bab1fb14a05d5737741e74e28c7b8b5a064de10142fad248",
"sha256:6cf9b429b21df6b99f4dee7a1218b8b7ffbbe7df8764dc0bd60ce8a0708fed1e",
"sha256:70b37199913c1bd300ff6e2693316c6f869c7ee16378faf10e4f5e3275b299c3",
"sha256:727fd05b57df37dc0bcf1a27767a3d9a78cbbc92822445f32cc3436ba797337b",
"sha256:74ae7b798248fe62021dbf3c914245ad45d1a6b0cb4a29ecb4b31d0bfbc4cc3e",
"sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0",
"sha256:86945f2ee6d10cdfd67bcb4069c1662dd711f7e2a4343db5cecec06b87cf31aa",
"sha256:86d835afea1eaa143012a2d7a3f45a3adce2d7adc8b4961f0b362214d800846a",
"sha256:872a5cf366aec6bb1147336480fef14c9164b154aeb6542327de4970282cd2f5",
"sha256:8b973c57ff8e184109db042c842423ff4f60446239bd585a5131cc47f06f789d",
"sha256:8cba086a43d54ca804ce711b2a940b16e452807acebe7852ff327f1ecd49b0d4",
"sha256:8f7f0e05112916223d3f438f293abf0727e1181b5983f413dfa2fefc4098245c",
"sha256:900218e456384ea676e24ea6a0417f030a3b07306d29d7ad843957b40a9d8d52",
"sha256:93eebbcf1aafdf7e2ddd44c2923e2672e1010bddc014138b229e49725b4d6be5",
"sha256:9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d",
"sha256:9ee2197ef8c4f0dfe405d835f3b6a14f5fee7782b5de51ba06fb65fc9b36e9f1",
"sha256:a414504bef8945eae5f2d7cb7be2d4af77c5d1cb5e20b296c2c25b61dff2900c",
"sha256:a4b9159734b326535f4dd01d947f919c6eefd2d9827466a696c44ced82dfbc18",
"sha256:a80afd79f45f3c4a7d341f13acbe058d1ca8ac017c165d3fa0d3de6bc1a079d7",
"sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188",
"sha256:acfd89508504a19ed06ef963ad544ec6664518c863436306153e13e94605c218",
"sha256:aeffcab3d4b43712bb7a60b65f6044d444e75e563ff6180af8f98dd4b905dfd2",
"sha256:afaffc4393205524af9dfa400fa250143a6c3bc646c08c9f5e25a9f4b4d6a903",
"sha256:b0c7088a73aef3d687c4deef8452a3ac7c1be4e29ed8bf3b366c8111128ac60c",
"sha256:b46b4ec24f7293f23adcd2d146960559aaf8020213de8ad1909dba6c013bf89c",
"sha256:b501b5fa195cc9e24fe102f21ec0a44dffc231d2af79950b451e0d99cea02234",
"sha256:bf06bc2af43fa8d32d30fae16ad965663e966b1a3202ed407b84c989c3221e82",
"sha256:c804e3a5aba5460c73955c955bdbd5c08c354954e9270a2c1565f62e866bdc39",
"sha256:c8a9958e88b65c3b27e22ca2a076311636850b612d6bbfb76e8d156aacde2aaf",
"sha256:cc0a57f895b96ec78969c34f682c602bf8da1a0270b09bc65673df2e7638ec20",
"sha256:cc8920d2ec5fa99875b670bb86ddeb21e295cb07aa331810d9e486e0b969d946",
"sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0",
"sha256:ce581db493ea1a96c0556360ede6607496e8bf9b3a8efa66e06477267bc831e9",
"sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff",
"sha256:d21644de1b609825ede2f48be98dfde4656aefc713654eeee280e37cadc4e0ad",
"sha256:d6889ec4ec662a1a37eb4b4fb26b6100841804dac55bd9df579e326cdc146227",
"sha256:de5672f4a7b200c15a4127042170a694d4df43c992948f5e1af57f0174beed10",
"sha256:e6a0bc88393d65807d751a614207b7129a310ca4fe76a74e5c7da5fa5671417e",
"sha256:ed89927b86296067b4f81f108a2271d8926467a8868e554eaf370fc27fa3ccaf",
"sha256:ee3888d9ff7c14604052b2ca5535a30216aa0a58e948cdd3eeb8d3415f638769",
"sha256:f0963b55cdd70fad460fa4c1341f12f976bb26cb66021a5580329bd498988310",
"sha256:f16417ec91f12f814b10bafe79ef77e70113a2f5f7018640e7425ff979253425",
"sha256:f28620fe26bee16243be2b7b874da327312240a7cdc38b769a697578d2100013",
"sha256:f4255143f5160d0de972d28c8f9665d882b5f61309d8362fdd3e103cf7bf010c",
"sha256:ffac52f28a7849ad7576293c0cb7b9f08304e8f7d738a8cb8a90ec4c55a998eb",
"sha256:ffe22d2b05504f786c867c8395de703937f934272eb67586817b46188b4ded6d",
"sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520"
],
"markers": "python_version >= '3.11'",
"version": "==2.3.5"
},
"scipy": {
"hashes": [
"sha256:0151a0749efeaaab78711c78422d413c583b8cdd2011a3c1d6c794938ee9fdb2",
"sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb",
"sha256:03192a35e661470197556de24e7cb1330d84b35b94ead65c46ad6f16f6b28f2a",
"sha256:0553371015692a898e1aa858fed67a3576c34edefa6b7ebdb4e9dde49ce5c203",
"sha256:062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304",
"sha256:0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959",
"sha256:0c623a54f7b79dd88ef56da19bc2873afec9673a48f3b85b18e4d402bdd29a5a",
"sha256:16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d",
"sha256:1fb2472e72e24d1530debe6ae078db70fb1605350c88a3d14bc401d6306dbffe",
"sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562",
"sha256:2a207a6ce9c24f1951241f4693ede2d393f59c07abc159b2cb2be980820e01fb",
"sha256:2b71d93c8a9936046866acebc915e2af2e292b883ed6e2cbe5c34beb094b82d9",
"sha256:2d1ae2cf0c350e7705168ff2429962a89ad90c2d49d1dd300686d8b2a5af22fc",
"sha256:3a4c460301fb2cffb7f88528f30b3127742cff583603aa7dc964a52c463b385d",
"sha256:3d4a07a8e785d80289dfe66b7c27d8634a773020742ec7187b85ccc4b0e7b686",
"sha256:40be6cf99e68b6c4321e9f8782e7d5ff8265af28ef2cd56e9c9b2638fa08ad97",
"sha256:4aff59800a3b7f786b70bfd6ab551001cb553244988d7d6b8299cb1ea653b353",
"sha256:50a3dbf286dbc7d84f176f9a1574c705f277cb6565069f88f60db9eafdbe3ee2",
"sha256:532fb5ad6a87e9e9cd9c959b106b73145a03f04c7d57ea3e6f6bb60b86ab0876",
"sha256:53c3844d527213631e886621df5695d35e4f6a75f620dca412bcd292f6b87d78",
"sha256:56edc65510d1331dae01ef9b658d428e33ed48b4f77b1d51caf479a0253f96dc",
"sha256:57d01cb6f85e34f0946b33caa66e892aae072b64b034183f3d87c4025802a119",
"sha256:5803c5fadd29de0cf27fa08ccbfe7a9e5d741bf63e4ab1085437266f12460ff9",
"sha256:6020470b9d00245926f2d5bb93b119ca0340f0d564eb6fbaad843eaebf9d690f",
"sha256:63d3cdacb8a824a295191a723ee5e4ea7768ca5ca5f2838532d9f2e2b3ce2135",
"sha256:663b8d66a8748051c3ee9c96465fb417509315b99c71550fda2591d7dd634234",
"sha256:72d1717fd3b5e6ec747327ce9bda32d5463f472c9dce9f54499e81fbd50245a1",
"sha256:7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88",
"sha256:7f68154688c515cdb541a31ef8eb66d8cd1050605be9dcd74199cbd22ac739bc",
"sha256:81fc5827606858cf71446a5e98715ba0e11f0dbc83d71c7409d05486592a45d6",
"sha256:875555ce62743e1d54f06cdf22c1e0bc47b91130ac40fe5d783b6dfa114beeb6",
"sha256:8b3c820ddb80029fe9f43d61b81d8b488d3ef8ca010d15122b152db77dc94c22",
"sha256:8be1ca9170fcb6223cc7c27f4305d680ded114a1567c0bd2bfcbf947d1b17511",
"sha256:8d09d72dc92742988b0e7750bddb8060b0c7079606c0d24a8cc8e9c9c11f9079",
"sha256:9452781bd879b14b6f055b26643703551320aa8d79ae064a71df55c00286a184",
"sha256:96491a6a54e995f00a28a3c3badfff58fd093bf26cd5fb34a2188c8c756a3a2c",
"sha256:9b9c9c07b6d56a35777a1b4cc8966118fb16cfd8daf6743867d17d36cfad2d40",
"sha256:a8a26c78ef223d3e30920ef759e25625a0ecdd0d60e5a8818b7513c3e5384cf2",
"sha256:aadd23f98f9cb069b3bd64ddc900c4d277778242e961751f77a8cb5c4b946fb0",
"sha256:b7180967113560cca57418a7bc719e30366b47959dd845a93206fbed693c867e",
"sha256:b7c5f1bda1354d6a19bc6af73a649f8285ca63ac6b52e64e658a5a11d4d69800",
"sha256:b81c27fc41954319a943d43b20e07c40bdcd3ff7cf013f4fb86286faefe546c4",
"sha256:bb61878c18a470021fb515a843dc7a76961a8daceaaaa8bad1332f1bf4b54657",
"sha256:bea0a62734d20d67608660f69dcda23e7f90fb4ca20974ab80b6ed40df87a005",
"sha256:c5192722cffe15f9329a3948c4b1db789fbb1f05c97899187dcf009b283aea70",
"sha256:c97176013d404c7346bf57874eaac5187d969293bf40497140b0a2b2b7482e07",
"sha256:cd13e354df9938598af2be05822c323e97132d5e6306b83a3b4ee6724c6e522e",
"sha256:d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c",
"sha256:d3837938ae715fc0fe3c39c0202de3a8853aff22ca66781ddc2ade7554b7e2cc",
"sha256:d9f48cafc7ce94cf9b15c6bffdc443a81a27bf7075cf2dcd5c8b40f85d10c4e7",
"sha256:da7763f55885045036fabcebd80144b757d3db06ab0861415d1c3b7c69042146",
"sha256:deb3841c925eeddb6afc1e4e4a45e418d19ec7b87c5df177695224078e8ec733",
"sha256:e1d27cbcb4602680a49d787d90664fa4974063ac9d4134813332a8c53dbe667c",
"sha256:e5d42a9472e7579e473879a1990327830493a7047506d58d73fc429b84c1d49d",
"sha256:e7efa2681ea410b10dde31a52b18b0154d66f2485328830e45fdf183af5aefc6",
"sha256:eab43fae33a0c39006a88096cd7b4f4ef545ea0447d250d5ac18202d40b6611d",
"sha256:f2622206f5559784fa5c4b53a950c3c7c1cf3e84ca1b9c4b6c03f062f289ca26",
"sha256:f379b54b77a597aa7ee5e697df0d66903e41b9c85a6dd7946159e356319158e8",
"sha256:f667a4542cc8917af1db06366d3f78a5c8e83badd56409f94d1eac8d8d9133fa",
"sha256:fb4b29f4cf8cc5a8d628bc8d8e26d12d7278cd1f219f22698a378c3d67db5e4b",
"sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d"
],
"index": "pypi",
"markers": "python_version >= '3.11'",
"version": "==1.16.3"
}
},
"develop": {}
}
インストールしたバージョンがわかります。
- numpy “version”: “==2.3.5”
- scipy “version”: “==1.16.3”
“hashes” はそのバージョンの各アーキテクチャごとのwhlファイルのハッシュの一覧です。
環境再現時に検証のために使います。
この PipfileとPipfile.lock があれば同じパッケージをインストールすることができます。
## projectをproject2へ複製した
ubuntu@x:~/project2$ pipenv sync
Creating a virtualenv for this project
Pipfile: /home/ubuntu/project2/Pipfile
Using /usr/bin/python33.12.3 to create virtualenv...
⠙ Creating virtual environment...created virtual environment CPython3.12.3.final.0-64 in 109ms
creator CPython3Posix(dest=/home/ubuntu/.local/share/virtualenvs/project2-ecrzWH4Z, clear=False, no_vcs_ignore=False,
global=False)
seeder FromAppData(download=False, pip=bundle, via=copy, app_data_dir=/home/ubuntu/.local/share/virtualenv)
added seed packages: pip==25.3
activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
✔ Successfully created virtual environment!
Virtualenv location: /home/ubuntu/.local/share/virtualenvs/project2-ecrzWH4Z
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Installing dependencies from Pipfile.lock (f11941)... # <== ロックファイルが使用されている
All dependencies are now up-to-date!
パッケージの使用例
pipenv run python で仮想環境下のPythonを使います。
main.py
import scipy
print(scipy.__version__)
ubuntu@x:~/project$ pipenv run python main.py
1.16.3
dev/prod分離
Pipfileに dev-packages の項目がありました。 pip/pip-toolsではファイルを分けて”こういう使い方をする”といった”やり方”で行っていたことを、Pipenvはツールとして組み込んでいるということです。
ubuntu@x:~/project$ pipenv install pytest --dev
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Installing pytest...
✔ Installation Succeeded
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Installing dependencies from Pipfile.lock (f11941)...
All dependencies are now up-to-date!
Upgrading pytest in dependencies.
Building requirements...
Resolving dependencies...
✔ Success!
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Installing dependencies from Pipfile.lock (e5836c)...
All dependencies are now up-to-date!
Installing dependencies from Pipfile.lock (e5836c)...
Installing dependencies from Pipfile.lock (e5836c)...
Pipfile (更新箇所)
[dev-packages]
pytest = "*"
Pifile.lock (更新箇所)
{
"_meta": {...},
"default": {...},
"develop": {
"iniconfig": {... },
"packaging": {... },
"pluggy": {... },
"pygments": {... },
"pytest": {
"hashes": [
"sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b",
"sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11"
],
"index": "pypi",
"markers": "python_version >= '3.10'",
"version": "==9.0.2"
}
}
}
pipenv sync --dev で devパッケージも含めてインストールされます。
ubuntu@x:~$ cp -r project project-dev
ubuntu@x:~/project$ cd project-dev
ubuntu@x:~/project-dev$ pipenv sync --dev
...
Installing dependencies from Pipfile.lock (e5836c)...
Installing dependencies from Pipfile.lock (e5836c)...
All dependencies are now up-to-date!
ubuntu@x:~/project-dev$ pipenv graph
pytest==9.0.2
├── iniconfig [required: >=1.0.1, installed: 2.3.0]
├── packaging [required: >=22, installed: 25.0]
├── pluggy [required: >=1.5,<2, installed: 1.6.0]
└── Pygments [required: >=2.7.2, installed: 2.19.2]
scipy==1.16.3
└── numpy [required: >=1.25.2,<2.6, installed: 2.3.5]
dev以外の区分を追加する場合は--categoriesで追加します。
## e2eカテゴリにseleniumを追加する
$ pipenv install --categories e2e selenium
Pipfile
[packages]
scipy = "*"
[dev-packages]
pytest = "*"
[requires]
python_version = "3.12"
[e2e]
selenium = "*"
Pipfileのみで管理する。これがPipenvです。
ディレクトリ構成
デフォルトでは仮想環境は$HOME以下で管理されます。
$HOME/
├── .local/share/virtualenvs/
│ └── project-ipe16O64/bin/python3 # プロジェクト名+ハッシュ
│ ├── bin/
│ │ └── python3
│ └── lib/
│ └── python3.12/
│ └── site-packages/
└── project/
├── Pipfile # 依存関係定義 (toml)
├── Pipfile.lock # ロックファイル (json)
└── main.py
内部
依存解決部分はpipのコードをpipenv用に修正したものを使用しているため基本的にpipの能力と同じです。
まとめ
Pythonでの開発ではvenv、パッケージロック、パッケージインストール対象切り替えを行うことが良い方法でした。
pipとpip-toolsで可能でしたが煩雑な手順で設定が散らばっていました。
これをPipfileとPipfile.lockのもとで管理してコマンドとしてやり方を標準化したのがPipenvです。
3.5 Poetry
Poetryは、仮想環境管理・依存関係管理・パッケージング・公開を統合したツールです。
Rye登場前はバージョン管理のpyenvなどと組み合わせて完全な開発ツールの位置づけでした。
また、パッケージの依存解決アルゴリズムも改善され高速になっています。
今現在でも十分使用に耐えるものです。
PEP準拠でpyproject.tomlを使います。ロックファイルはpoetry.lockです。
セットアップ例
PythonランタイムはシステムPythonを使います。
## コンテナ起動
$ docker run -it --rm --hostname "x" ubuntu:noble bash
## システムPythonとcurlインストール
root@x:/# apt update; apt install -y curl python3;
## ubuntuユーザーへ切り替え
root@x:/# su - ubuntu
ubuntu@x:~$ pwd
/home/ubuntu
## Poetryインストール
ubuntu@x:~$ curl -sSL https://install.python-poetry.org | python3 -
Retrieving Poetry metadata
# Welcome to Poetry!
This will download and install the latest version of Poetry,
a dependency and package manager for Python.
It will add the `poetry` command to Poetry's bin directory, located at:
/home/ubuntu/.local/bin
You can uninstall at any time by executing this script with the --uninstall option,
and these changes will be reverted.
Installing Poetry (2.2.1): Done
Poetry (2.2.1) is installed now. Great!
To get started you need Poetry's bin directory (/home/ubuntu/.local/bin) in your `PATH`
environment variable.
Add `export PATH="/home/ubuntu/.local/bin:$PATH"` to your shell configuration file.
Alternatively, you can call Poetry explicitly with `/home/ubuntu/.local/bin/poetry`.
You can test that everything is set up by executing:
`poetry --version`
## ~/.bashrc
ubuntu@x:~$ exec $SHELL -l
ubuntu@x:~$ poetry --version
Poetry (version 2.2.1)
~/.profile に ~/.local/binのパスの追加があるので追加の設定は不要でBashの環境をリロードするだけでpoetryが使用できます。
.profile
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
poetry new で新規プロジェクトとディレクトリを作成します。
ubuntu@x:~$ poetry new project
Created package project in project
ubuntu@x:~$ cd project/
ubuntu@x:~/project$ ls
README.md pyproject.toml src tests
既存のディレクトリをプロジェクトとしてセットアップする poetry init もあります。
仮想環境
プロジェクトディレクトリ内の初回操作のときに自動で仮想環境(virtualenv)が作成されます。
site-packagesが~/.cache/pypoetry/virtualenvs/の下の一意なプロジェクト専用の環境を参照できるようになっています。
ubuntu@x:~/project$ poetry run python
Creating virtualenv project-4hf1KBS2-py3.12 in /home/ubuntu/.cache/pypoetry/virtualenvs
Python 3.12.3 (main, Nov 6 2025, 13:44:16) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> for p in sys.path:
... print(p)
...
/usr/lib/python312.zip
/usr/lib/python3.12
/usr/lib/python3.12/lib-dynload
/home/ubuntu/.cache/pypoetry/virtualenvs/project-4hf1KBS2-py3.12/lib/python3.12/site-packages
※ 仮想環境の作成場所は設定でプロジェクト内の.venvにすることも可能です。
https://python-poetry.org/docs/configuration/#virtualenvsin-project
poetry runで仮想環境下にあるPython環境を使います。
ubuntu@x:~$ cd myproject
ubuntu@x:~/myproject$ poetry add requests
Creating virtualenv myproject in /home/ubuntu/myproject/.venv
Using version ^2.32.5 for requests
ubuntu@x:~/myproject$ poetry run python main.py
ubuntu@x:~/myproject$ poetry run pytest
poetry env activateによってvenvのようにシェルへ環境変数などを適用して使う方法もあります。
## poetry env activte はシェルへ環境を適用するためのコマンド文字列を出力します
ubuntu@x:~/project$ poetry env activate
source /home/ubuntu/.cache/pypoetry/virtualenvs/project-4hf1KBS2-py3.12/bin/activate
## Bashでの適用例
ubuntu@x:~/project$ $(poetry env activate)
(project-py3.12) ubuntu@x:~/project$ which python3
/home/ubuntu/.cache/pypoetry/virtualenvs/project-4hf1KBS2-py3.12/bin/python3
venvと同様にpython スクリプトと実行したい場合はシェルに環境を設定できますが、poetryコマンドを使う作業が多いため、特に推奨されるものではありません。
パッケージ管理
プロジェクト作成後初期状態のdependenciesは空です。
pyproject.toml 初期状態
[project]
name = "project"
version = "0.1.0"
description = ""
authors = [
{name = "Your Name",email = "you@example.com"}
]
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
]
[tool.poetry]
packages = [{include = "project", from = "src"}]
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
scipyを追加します。scipyはnumpyに依存しています。
ubuntu@x:~/project$ poetry add scipy
Using version ^1.16.3 for scipy
Updating dependencies
Resolving dependencies... (0.4s)
Package operations: 2 installs, 0 updates, 0 removals
- Installing numpy (2.3.5)
- Installing scipy (1.16.3)
Writing lock file
pyproject.tomlにdependenciesが記録されます。
pyproject.toml
[project]
name = "project"
version = "0.1.0"
description = ""
authors = [
{name = "Your Name",email = "you@example.com"}
]
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"scipy (>=1.16.3,<2.0.0)"
]
[tool.poetry]
packages = [{include = "project", from = "src"}]
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
Writing lock file これは実際にインストールされたパッケージの記録があるロックファイルです。
poetry.lock (抜粋)
[[package]]
name = "numpy"
version = "2.3.5"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.11"
groups = ["main"]
files = [
{file = "numpy-2.3.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de5672f4a7b200c15a4127042170a694d4df43c992948f5e1af57f0174beed10"},
...
{file = "numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0"},
]
[[package]]
name = "scipy"
version = "1.16.3"
description = "Fundamental algorithms for scientific computing in Python"
optional = false
python-versions = ">=3.11"
groups = ["main"]
files = [
{file = "scipy-1.16.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:40be6cf99e68b6c4321e9f8782e7d5ff8265af28ef2cd56e9c9b2638fa08ad97"},
...
{file = "scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb"},
]
[package.dependencies]
numpy = ">=1.25.2,<2.6"
poetry.lock (全文)
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
[[package]]
name = "numpy"
version = "2.3.5"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.11"
groups = ["main"]
files = [
{file = "numpy-2.3.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de5672f4a7b200c15a4127042170a694d4df43c992948f5e1af57f0174beed10"},
{file = "numpy-2.3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:acfd89508504a19ed06ef963ad544ec6664518c863436306153e13e94605c218"},
{file = "numpy-2.3.5-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:ffe22d2b05504f786c867c8395de703937f934272eb67586817b46188b4ded6d"},
{file = "numpy-2.3.5-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:872a5cf366aec6bb1147336480fef14c9164b154aeb6542327de4970282cd2f5"},
{file = "numpy-2.3.5-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3095bdb8dd297e5920b010e96134ed91d852d81d490e787beca7e35ae1d89cf7"},
{file = "numpy-2.3.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cba086a43d54ca804ce711b2a940b16e452807acebe7852ff327f1ecd49b0d4"},
{file = "numpy-2.3.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6cf9b429b21df6b99f4dee7a1218b8b7ffbbe7df8764dc0bd60ce8a0708fed1e"},
{file = "numpy-2.3.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:396084a36abdb603546b119d96528c2f6263921c50df3c8fd7cb28873a237748"},
{file = "numpy-2.3.5-cp311-cp311-win32.whl", hash = "sha256:b0c7088a73aef3d687c4deef8452a3ac7c1be4e29ed8bf3b366c8111128ac60c"},
{file = "numpy-2.3.5-cp311-cp311-win_amd64.whl", hash = "sha256:a414504bef8945eae5f2d7cb7be2d4af77c5d1cb5e20b296c2c25b61dff2900c"},
{file = "numpy-2.3.5-cp311-cp311-win_arm64.whl", hash = "sha256:0cd00b7b36e35398fa2d16af7b907b65304ef8bb4817a550e06e5012929830fa"},
{file = "numpy-2.3.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:74ae7b798248fe62021dbf3c914245ad45d1a6b0cb4a29ecb4b31d0bfbc4cc3e"},
{file = "numpy-2.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee3888d9ff7c14604052b2ca5535a30216aa0a58e948cdd3eeb8d3415f638769"},
{file = "numpy-2.3.5-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:612a95a17655e213502f60cfb9bf9408efdc9eb1d5f50535cc6eb365d11b42b5"},
{file = "numpy-2.3.5-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3101e5177d114a593d79dd79658650fe28b5a0d8abeb8ce6f437c0e6df5be1a4"},
{file = "numpy-2.3.5-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b973c57ff8e184109db042c842423ff4f60446239bd585a5131cc47f06f789d"},
{file = "numpy-2.3.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d8163f43acde9a73c2a33605353a4f1bc4798745a8b1d73183b28e5b435ae28"},
{file = "numpy-2.3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:51c1e14eb1e154ebd80e860722f9e6ed6ec89714ad2db2d3aa33c31d7c12179b"},
{file = "numpy-2.3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b46b4ec24f7293f23adcd2d146960559aaf8020213de8ad1909dba6c013bf89c"},
{file = "numpy-2.3.5-cp312-cp312-win32.whl", hash = "sha256:3997b5b3c9a771e157f9aae01dd579ee35ad7109be18db0e85dbdbe1de06e952"},
{file = "numpy-2.3.5-cp312-cp312-win_amd64.whl", hash = "sha256:86945f2ee6d10cdfd67bcb4069c1662dd711f7e2a4343db5cecec06b87cf31aa"},
{file = "numpy-2.3.5-cp312-cp312-win_arm64.whl", hash = "sha256:f28620fe26bee16243be2b7b874da327312240a7cdc38b769a697578d2100013"},
{file = "numpy-2.3.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff"},
{file = "numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188"},
{file = "numpy-2.3.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0"},
{file = "numpy-2.3.5-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:afaffc4393205524af9dfa400fa250143a6c3bc646c08c9f5e25a9f4b4d6a903"},
{file = "numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d"},
{file = "numpy-2.3.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017"},
{file = "numpy-2.3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed89927b86296067b4f81f108a2271d8926467a8868e554eaf370fc27fa3ccaf"},
{file = "numpy-2.3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51c55fe3451421f3a6ef9a9c1439e82101c57a2c9eab9feb196a62b1a10b58ce"},
{file = "numpy-2.3.5-cp313-cp313-win32.whl", hash = "sha256:1978155dd49972084bd6ef388d66ab70f0c323ddee6f693d539376498720fb7e"},
{file = "numpy-2.3.5-cp313-cp313-win_amd64.whl", hash = "sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b"},
{file = "numpy-2.3.5-cp313-cp313-win_arm64.whl", hash = "sha256:0472f11f6ec23a74a906a00b48a4dcf3849209696dff7c189714511268d103ae"},
{file = "numpy-2.3.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:414802f3b97f3c1eef41e530aaba3b3c1620649871d8cb38c6eaff034c2e16bd"},
{file = "numpy-2.3.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5ee6609ac3604fa7780e30a03e5e241a7956f8e2fcfe547d51e3afa5247ac47f"},
{file = "numpy-2.3.5-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:86d835afea1eaa143012a2d7a3f45a3adce2d7adc8b4961f0b362214d800846a"},
{file = "numpy-2.3.5-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:30bc11310e8153ca664b14c5f1b73e94bd0503681fcf136a163de856f3a50139"},
{file = "numpy-2.3.5-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1062fde1dcf469571705945b0f221b73928f34a20c904ffb45db101907c3454e"},
{file = "numpy-2.3.5-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce581db493ea1a96c0556360ede6607496e8bf9b3a8efa66e06477267bc831e9"},
{file = "numpy-2.3.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:cc8920d2ec5fa99875b670bb86ddeb21e295cb07aa331810d9e486e0b969d946"},
{file = "numpy-2.3.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9ee2197ef8c4f0dfe405d835f3b6a14f5fee7782b5de51ba06fb65fc9b36e9f1"},
{file = "numpy-2.3.5-cp313-cp313t-win32.whl", hash = "sha256:70b37199913c1bd300ff6e2693316c6f869c7ee16378faf10e4f5e3275b299c3"},
{file = "numpy-2.3.5-cp313-cp313t-win_amd64.whl", hash = "sha256:b501b5fa195cc9e24fe102f21ec0a44dffc231d2af79950b451e0d99cea02234"},
{file = "numpy-2.3.5-cp313-cp313t-win_arm64.whl", hash = "sha256:a80afd79f45f3c4a7d341f13acbe058d1ca8ac017c165d3fa0d3de6bc1a079d7"},
{file = "numpy-2.3.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:bf06bc2af43fa8d32d30fae16ad965663e966b1a3202ed407b84c989c3221e82"},
{file = "numpy-2.3.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:052e8c42e0c49d2575621c158934920524f6c5da05a1d3b9bab5d8e259e045f0"},
{file = "numpy-2.3.5-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:1ed1ec893cff7040a02c8aa1c8611b94d395590d553f6b53629a4461dc7f7b63"},
{file = "numpy-2.3.5-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:2dcd0808a421a482a080f89859a18beb0b3d1e905b81e617a188bd80422d62e9"},
{file = "numpy-2.3.5-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:727fd05b57df37dc0bcf1a27767a3d9a78cbbc92822445f32cc3436ba797337b"},
{file = "numpy-2.3.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520"},
{file = "numpy-2.3.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8f7f0e05112916223d3f438f293abf0727e1181b5983f413dfa2fefc4098245c"},
{file = "numpy-2.3.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2e2eb32ddb9ccb817d620ac1d8dae7c3f641c1e5f55f531a33e8ab97960a75b8"},
{file = "numpy-2.3.5-cp314-cp314-win32.whl", hash = "sha256:66f85ce62c70b843bab1fb14a05d5737741e74e28c7b8b5a064de10142fad248"},
{file = "numpy-2.3.5-cp314-cp314-win_amd64.whl", hash = "sha256:e6a0bc88393d65807d751a614207b7129a310ca4fe76a74e5c7da5fa5671417e"},
{file = "numpy-2.3.5-cp314-cp314-win_arm64.whl", hash = "sha256:aeffcab3d4b43712bb7a60b65f6044d444e75e563ff6180af8f98dd4b905dfd2"},
{file = "numpy-2.3.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:17531366a2e3a9e30762c000f2c43a9aaa05728712e25c11ce1dbe700c53ad41"},
{file = "numpy-2.3.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d21644de1b609825ede2f48be98dfde4656aefc713654eeee280e37cadc4e0ad"},
{file = "numpy-2.3.5-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:c804e3a5aba5460c73955c955bdbd5c08c354954e9270a2c1565f62e866bdc39"},
{file = "numpy-2.3.5-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:cc0a57f895b96ec78969c34f682c602bf8da1a0270b09bc65673df2e7638ec20"},
{file = "numpy-2.3.5-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:900218e456384ea676e24ea6a0417f030a3b07306d29d7ad843957b40a9d8d52"},
{file = "numpy-2.3.5-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09a1bea522b25109bf8e6f3027bd810f7c1085c64a0c7ce050c1676ad0ba010b"},
{file = "numpy-2.3.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:04822c00b5fd0323c8166d66c701dc31b7fbd252c100acd708c48f763968d6a3"},
{file = "numpy-2.3.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d6889ec4ec662a1a37eb4b4fb26b6100841804dac55bd9df579e326cdc146227"},
{file = "numpy-2.3.5-cp314-cp314t-win32.whl", hash = "sha256:93eebbcf1aafdf7e2ddd44c2923e2672e1010bddc014138b229e49725b4d6be5"},
{file = "numpy-2.3.5-cp314-cp314t-win_amd64.whl", hash = "sha256:c8a9958e88b65c3b27e22ca2a076311636850b612d6bbfb76e8d156aacde2aaf"},
{file = "numpy-2.3.5-cp314-cp314t-win_arm64.whl", hash = "sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42"},
{file = "numpy-2.3.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f0963b55cdd70fad460fa4c1341f12f976bb26cb66021a5580329bd498988310"},
{file = "numpy-2.3.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f4255143f5160d0de972d28c8f9665d882b5f61309d8362fdd3e103cf7bf010c"},
{file = "numpy-2.3.5-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:a4b9159734b326535f4dd01d947f919c6eefd2d9827466a696c44ced82dfbc18"},
{file = "numpy-2.3.5-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2feae0d2c91d46e59fcd62784a3a83b3fb677fead592ce51b5a6fbb4f95965ff"},
{file = "numpy-2.3.5-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffac52f28a7849ad7576293c0cb7b9f08304e8f7d738a8cb8a90ec4c55a998eb"},
{file = "numpy-2.3.5-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63c0e9e7eea69588479ebf4a8a270d5ac22763cc5854e9a7eae952a3908103f7"},
{file = "numpy-2.3.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f16417ec91f12f814b10bafe79ef77e70113a2f5f7018640e7425ff979253425"},
{file = "numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0"},
]
[[package]]
name = "scipy"
version = "1.16.3"
description = "Fundamental algorithms for scientific computing in Python"
optional = false
python-versions = ">=3.11"
groups = ["main"]
files = [
{file = "scipy-1.16.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:40be6cf99e68b6c4321e9f8782e7d5ff8265af28ef2cd56e9c9b2638fa08ad97"},
{file = "scipy-1.16.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:8be1ca9170fcb6223cc7c27f4305d680ded114a1567c0bd2bfcbf947d1b17511"},
{file = "scipy-1.16.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:bea0a62734d20d67608660f69dcda23e7f90fb4ca20974ab80b6ed40df87a005"},
{file = "scipy-1.16.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:2a207a6ce9c24f1951241f4693ede2d393f59c07abc159b2cb2be980820e01fb"},
{file = "scipy-1.16.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:532fb5ad6a87e9e9cd9c959b106b73145a03f04c7d57ea3e6f6bb60b86ab0876"},
{file = "scipy-1.16.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0151a0749efeaaab78711c78422d413c583b8cdd2011a3c1d6c794938ee9fdb2"},
{file = "scipy-1.16.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7180967113560cca57418a7bc719e30366b47959dd845a93206fbed693c867e"},
{file = "scipy-1.16.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:deb3841c925eeddb6afc1e4e4a45e418d19ec7b87c5df177695224078e8ec733"},
{file = "scipy-1.16.3-cp311-cp311-win_amd64.whl", hash = "sha256:53c3844d527213631e886621df5695d35e4f6a75f620dca412bcd292f6b87d78"},
{file = "scipy-1.16.3-cp311-cp311-win_arm64.whl", hash = "sha256:9452781bd879b14b6f055b26643703551320aa8d79ae064a71df55c00286a184"},
{file = "scipy-1.16.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:81fc5827606858cf71446a5e98715ba0e11f0dbc83d71c7409d05486592a45d6"},
{file = "scipy-1.16.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:c97176013d404c7346bf57874eaac5187d969293bf40497140b0a2b2b7482e07"},
{file = "scipy-1.16.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2b71d93c8a9936046866acebc915e2af2e292b883ed6e2cbe5c34beb094b82d9"},
{file = "scipy-1.16.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3d4a07a8e785d80289dfe66b7c27d8634a773020742ec7187b85ccc4b0e7b686"},
{file = "scipy-1.16.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0553371015692a898e1aa858fed67a3576c34edefa6b7ebdb4e9dde49ce5c203"},
{file = "scipy-1.16.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:72d1717fd3b5e6ec747327ce9bda32d5463f472c9dce9f54499e81fbd50245a1"},
{file = "scipy-1.16.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fb2472e72e24d1530debe6ae078db70fb1605350c88a3d14bc401d6306dbffe"},
{file = "scipy-1.16.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c5192722cffe15f9329a3948c4b1db789fbb1f05c97899187dcf009b283aea70"},
{file = "scipy-1.16.3-cp312-cp312-win_amd64.whl", hash = "sha256:56edc65510d1331dae01ef9b658d428e33ed48b4f77b1d51caf479a0253f96dc"},
{file = "scipy-1.16.3-cp312-cp312-win_arm64.whl", hash = "sha256:a8a26c78ef223d3e30920ef759e25625a0ecdd0d60e5a8818b7513c3e5384cf2"},
{file = "scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c"},
{file = "scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d"},
{file = "scipy-1.16.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:5803c5fadd29de0cf27fa08ccbfe7a9e5d741bf63e4ab1085437266f12460ff9"},
{file = "scipy-1.16.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:b81c27fc41954319a943d43b20e07c40bdcd3ff7cf013f4fb86286faefe546c4"},
{file = "scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959"},
{file = "scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88"},
{file = "scipy-1.16.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:663b8d66a8748051c3ee9c96465fb417509315b99c71550fda2591d7dd634234"},
{file = "scipy-1.16.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eab43fae33a0c39006a88096cd7b4f4ef545ea0447d250d5ac18202d40b6611d"},
{file = "scipy-1.16.3-cp313-cp313-win_amd64.whl", hash = "sha256:062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304"},
{file = "scipy-1.16.3-cp313-cp313-win_arm64.whl", hash = "sha256:50a3dbf286dbc7d84f176f9a1574c705f277cb6565069f88f60db9eafdbe3ee2"},
{file = "scipy-1.16.3-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:fb4b29f4cf8cc5a8d628bc8d8e26d12d7278cd1f219f22698a378c3d67db5e4b"},
{file = "scipy-1.16.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:8d09d72dc92742988b0e7750bddb8060b0c7079606c0d24a8cc8e9c9c11f9079"},
{file = "scipy-1.16.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:03192a35e661470197556de24e7cb1330d84b35b94ead65c46ad6f16f6b28f2a"},
{file = "scipy-1.16.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:57d01cb6f85e34f0946b33caa66e892aae072b64b034183f3d87c4025802a119"},
{file = "scipy-1.16.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:96491a6a54e995f00a28a3c3badfff58fd093bf26cd5fb34a2188c8c756a3a2c"},
{file = "scipy-1.16.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cd13e354df9938598af2be05822c323e97132d5e6306b83a3b4ee6724c6e522e"},
{file = "scipy-1.16.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:63d3cdacb8a824a295191a723ee5e4ea7768ca5ca5f2838532d9f2e2b3ce2135"},
{file = "scipy-1.16.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e7efa2681ea410b10dde31a52b18b0154d66f2485328830e45fdf183af5aefc6"},
{file = "scipy-1.16.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2d1ae2cf0c350e7705168ff2429962a89ad90c2d49d1dd300686d8b2a5af22fc"},
{file = "scipy-1.16.3-cp313-cp313t-win_arm64.whl", hash = "sha256:0c623a54f7b79dd88ef56da19bc2873afec9673a48f3b85b18e4d402bdd29a5a"},
{file = "scipy-1.16.3-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:875555ce62743e1d54f06cdf22c1e0bc47b91130ac40fe5d783b6dfa114beeb6"},
{file = "scipy-1.16.3-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:bb61878c18a470021fb515a843dc7a76961a8daceaaaa8bad1332f1bf4b54657"},
{file = "scipy-1.16.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2622206f5559784fa5c4b53a950c3c7c1cf3e84ca1b9c4b6c03f062f289ca26"},
{file = "scipy-1.16.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7f68154688c515cdb541a31ef8eb66d8cd1050605be9dcd74199cbd22ac739bc"},
{file = "scipy-1.16.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3c820ddb80029fe9f43d61b81d8b488d3ef8ca010d15122b152db77dc94c22"},
{file = "scipy-1.16.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3837938ae715fc0fe3c39c0202de3a8853aff22ca66781ddc2ade7554b7e2cc"},
{file = "scipy-1.16.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aadd23f98f9cb069b3bd64ddc900c4d277778242e961751f77a8cb5c4b946fb0"},
{file = "scipy-1.16.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b7c5f1bda1354d6a19bc6af73a649f8285ca63ac6b52e64e658a5a11d4d69800"},
{file = "scipy-1.16.3-cp314-cp314-win_amd64.whl", hash = "sha256:e5d42a9472e7579e473879a1990327830493a7047506d58d73fc429b84c1d49d"},
{file = "scipy-1.16.3-cp314-cp314-win_arm64.whl", hash = "sha256:6020470b9d00245926f2d5bb93b119ca0340f0d564eb6fbaad843eaebf9d690f"},
{file = "scipy-1.16.3-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:e1d27cbcb4602680a49d787d90664fa4974063ac9d4134813332a8c53dbe667c"},
{file = "scipy-1.16.3-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9b9c9c07b6d56a35777a1b4cc8966118fb16cfd8daf6743867d17d36cfad2d40"},
{file = "scipy-1.16.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:3a4c460301fb2cffb7f88528f30b3127742cff583603aa7dc964a52c463b385d"},
{file = "scipy-1.16.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:f667a4542cc8917af1db06366d3f78a5c8e83badd56409f94d1eac8d8d9133fa"},
{file = "scipy-1.16.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f379b54b77a597aa7ee5e697df0d66903e41b9c85a6dd7946159e356319158e8"},
{file = "scipy-1.16.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4aff59800a3b7f786b70bfd6ab551001cb553244988d7d6b8299cb1ea653b353"},
{file = "scipy-1.16.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:da7763f55885045036fabcebd80144b757d3db06ab0861415d1c3b7c69042146"},
{file = "scipy-1.16.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d"},
{file = "scipy-1.16.3-cp314-cp314t-win_amd64.whl", hash = "sha256:d9f48cafc7ce94cf9b15c6bffdc443a81a27bf7075cf2dcd5c8b40f85d10c4e7"},
{file = "scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562"},
{file = "scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb"},
]
[package.dependencies]
numpy = ">=1.25.2,<2.6"
[package.extras]
dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"]
doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "linkify-it-py", "matplotlib (>=3.5)", "myst-nb (>=1.2.0)", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.2.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"]
test = ["Cython", "array-api-strict (>=2.3.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest (>=8.0.0)", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
[metadata]
lock-version = "2.1"
python-versions = ">=3.12"
content-hash = "ff223f532d0f886ecefee3e39ce293d0d5b19df87c63c34f6c6bcf5871c01835"
scipyが依存するnumpyもロックファイルに記録されています。これにより依存関係が明確になります。
このロックファイルを使って同じパッケージ環境をpoetry installでセットアップすることができます。
ubuntu@x:~/project$ poetry install
Installing dependencies from lock file
依存解決
複数のパッケージの依存関係をpipがナイーブ(素朴)なアルゴリズムで解決するのに対して、Poetryは改善したアルゴリズムを使用するので高速になっています。
アルゴリズムはPubGrubらしい。
dev/prod分離
開発環境でのみインストールするといった場合は poetry add のときに group を指定します。
ubuntu@x:~/project$ poetry add pytest --group dev
Using version ^9.0.2 for pytest
Updating dependencies
Resolving dependencies... (0.1s)
Package operations: 5 installs, 0 updates, 0 removals
- Installing iniconfig (2.3.0)
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pygments (2.19.2)
- Installing pytest (9.0.2)
Writing lock file
pyproject.toml 抜粋
dependencies = [
"scipy (>=1.16.3,<2.0.0)"
]
[dependency-groups]
dev = [
"pytest (>=9.0.2,<10.0.0)"
]
poetry install のオプションでインストール対象を選択します。
$ poetry install # すべてインストール
$ poetry install --without dev # 本番環境用
$ poetry install --only main # 本番環境のみ
poetry install 実行例
pytestも含めてインストール poetry install
ubuntu@x:~/project-copy$ poetry instal
The requested command instal does not exist.
Did you mean one of these perhaps?
install: Installs the project dependencies.
python install: Install the specified Python version from the Python Standalone Builds project. (experimental feature)
self install: Install locked packages (incl. addons) required by this Poetry installation.
Documentation: https://python-poetry.org/docs/cli/
ubuntu@x:~/project-copy$ poetry install
Creating virtualenv project-xDhUDCti-py3.12 in /home/ubuntu/.cache/pypoetry/virtualenvs
Installing dependencies from lock file
Package operations: 7 installs, 0 updates, 0 removals
- Installing iniconfig (2.3.0)
- Installing numpy (2.3.5)
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pygments (2.19.2)
- Installing pytest (9.0.2)
- Installing scipy (1.16.3)
Installing the current project: project (0.1.0)
Pytestが入らない poetry install --only main
ubuntu@x:~/project-copy2$ poetry install --only main
Creating virtualenv project-6YKT1nMb-py3.12 in /home/ubuntu/.cache/pypoetry/virtualenvs
Installing dependencies from lock file
Package operations: 2 installs, 0 updates, 0 removals
- Installing numpy (2.3.5)
- Installing scipy (1.16.3)
Installing the current project: project (0.1.0)
ディレクトリ構成
pyproject.toml と poetry.lock があるディレクトリで poetry install をすると自動で仮想環境の作成とライブラリのインストールが完了します。
$HOME/
├── .cache/pypoetry/virtualenvs/
│ └── project-4hf1KBS2-py3.12/
│ ├── bin/
│ │ └── python3 # 任意のPython3へのシンボリックリンク
│ └── lib/
│ └── python3.12/
│ └── site-packages/
└── projects/
├── pyproject.toml # プロジェクト設定
├── poetry.lock # ロックファイル
├── src/
└── tests/
Poetry 仮想環境・パッケージ編
pyproject.tomlとpoetry.lockからPoetryが環境を作ってくれます。
Pythonバージョンは管理しません。
Poetry実行時にpyproject.tomlのrequires-pythonの要求に合うPythonバージョンかをチェックします。
例: Python3.12の環境で3.13以上を求めた場合
ubuntu@x:~/project-copy3$ python3 --version
Python 3.12.3
ubuntu@x:~/project-copy3$ grep requires-python pyproject.toml
requires-python = ">=3.13"
ubuntu@x:~/project$ poetry add requests
Current Python version (3.12.3) is not allowed by the project (>=3.13).
Please change python executable via the "env use" command.
3.6 Rye
pipenvとpoetryがバージョン管理を対象しなかったのに対してryeがすべてを管理することができるツールとして現れました。
仮想環境
プロジェクトを作成します。 (セットアップは Part 2: 🐍 Pythonバージョン管理 > 2.4 Rye にあります。)
## プロジェクト作成
ubuntu@x:~$ rye init project
success: Initialized project in /home/ubuntu/project
Run `rye sync` to get started
ubuntu@x:~$ cd project/
ubuntu@x:~/project$ ls
README.md pyproject.toml src
## バージョン指定
ubuntu@x:~/project$ rye pin 3.13
pinned 3.13.2 in /home/ubuntu/project/.python-version
ubuntu@x:~/project$ cat .python-version
3.13.2
## インストール
ubuntu@x:~/project$ rye run python
Downloading cpython@3.13.2
Checking checksum
Unpacking
Downloaded cpython@3.13.2
Initializing new virtualenv in /home/ubuntu/project/.venv
Python version: cpython@3.13.2
Python 3.13.2 (main, Feb 12 2025, 14:51:17) [Clang 19.1.6 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
ディレクトリ構成
ディレクトリ構成
$HOME/
├── .rye/
│ ├── shims/
│ │ ├── python (hardlink)
│ │ ├── python3 (hardlink)
│ │ └── rye (hardlink)
│ └── py/
│ ├── cpython@3.12.9/
│ │ ├── bin/
│ │ ├── python -> python3.12
│ │ ├── python3 -> python3.12
│ │ └── python3.12
│ └── cpython@3.13.2/
|
└── project/
├── .venv/
├── .python-version
└── pyproject.toml
.rye/shims/ の下は同じバイナリです。呼び出され方で動作を切り替えています。
動作は次のようになります。
- プロジェクト内で python を呼ぶ
- shims/ の python が呼ばれる。 (shims)
- shims がディレクトリを確認する
- .venv の python を使う
パッケージ管理
pyproject.toml 初期状態
[project]
name = "project"
version = "0.1.0"
description = "Add your description here"
dependencies = []
readme = "README.md"
requires-python = ">= 3.8"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.rye]
managed = true
dev-dependencies = []
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["src/project"]
scipyを入れます。
ubuntu@x:~/project$ rye add scipy
Added scipy>=1.16.3 as regular dependency
Reusing already existing virtualenv
Generating production lockfile: /home/ubuntu/project/requirements.lock
Generating dev lockfile: /home/ubuntu/project/requirements-dev.lock
Installing dependencies
Resolved 3 packages in 4ms
Built project @ file:///home/ubuntu/project
Prepared 1 package in 290ms
Installed 3 packages in 71ms
+ numpy==2.3.5
+ project==0.1.0 (from file:///home/ubuntu/project)
+ scipy==1.16.3
Done!
ubuntu@x:~/project$ ls
README.md pyproject.toml requirements-dev.lock requirements.lock src
pyproject.tomlにdependenciesが追加されています。
[project]
dependencies = [
"scipy>=1.16.3",
]
Poetryは "scipy (>=1.16.3,<2.0.0)" でした。pyproject.tomlに記述されることは同じですが微妙な差異はあります。
特徴的なのはrequirements.lockです。
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false
# generate-hashes: false
# universal: false
-e file:.
numpy==2.3.5
# via scipy
scipy==1.16.3
# via project
Pipenv, Poetry とは代わってハッシュのリストなどは無くrequirements.txtの書式でバージョンが指定されています。
これは内部でpip-compileを呼び出して生成されています。
この形のメリットはRyeが無くてもpipのみでインストール可能ということです。
開発中はRyeを使い、リリースはDockerのPythonイメージにツールを追加することなくrequirements.lockをpip installできることです。
Ryeは実用の面でやはり素晴らしいです。
ハッシュ生成をするには--generate-hashesを付けます。
ubuntu@x:~/project$ rye lock --generate-hashes
Generating production lockfile: /home/ubuntu/project/requirements.lock
Generating dev lockfile: /home/ubuntu/project/requirements-dev.lock
Done!
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false
# generate-hashes: true
# universal: false
-e file:.
numpy==2.3.5 \
--hash=sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b \
省略
--hash=sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520
# via scipy
scipy==1.16.3 \
--hash=sha256:0151a0749efeaaab78711c78422d413c583b8cdd2011a3c1d6c794938ee9fdb2 \
省略
--hash=sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d
# via project
Platform Compatibility
https://rye.astral.sh/guide/sync/#platform-compatibility
WindowsとLinuxで別のパッケージを使うとします。
dependencies = [
"scipy>=1.16.3",
# Linuxの場合のみ distro をインストールする
"distro; sys_platform == 'linux'",
# Windowsの場合のみ colorama をインストールする
"colorama; sys_platform == 'win32'"
]
これを Linux で rye sync すると distro のみが現れます。
requirements.lock (一部)
# last locked with the following flags:
# universal: false
-e file:.
distro==1.9.0
# via project
numpy==2.3.5
# via scipy
scipy==1.16.3
# via project
rye sync --universal で全て記録されるクロスプラットフォームのロックファイルができます。
requirements.lock (一部)
# last locked with the following flags:
# universal: true
-e file:.
colorama==0.4.6 ; sys_platform == 'win32'
# via project
distro==1.9.0 ; sys_platform == 'linux'
# via project
numpy==2.3.5
# via scipy
scipy==1.16.3
# via project
内部的にはuvの機能です。
ちなみに2回目以降、requirements.lockがある場合のrye syncのオプションは未指定の場合、lockファイル先頭に書いてある
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false
# generate-hashes: false
# universal: true
に従うようです。
dev/prod分離
requirements-dev.lock がディレクトリにあることからわかるように開発環境用パッケージの区分があります。
ubuntu@x:~/project$ rye add --dev pytest
Added pytest>=9.0.2 as dev dependency
pyproject.toml (関連個所)
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=9.0.2",
]
Rye では tool.rye セクションに置かれます。
Poetryでは dependency-groups セクションにあります。
[dependency-groups]
dev = [
"pytest (>=9.0.2,<10.0.0)"
]
dependency-groupの提案は PEP 735 https://packaging.python.org/en/latest/specifications/dependency-groups/ です。
https://github.com/astral-sh/rye/issues/421 対応が見送られたまま開発終了となりました。
まとめ
パッケージ管理も機能が十分にあるツールです。
ロックファイルのrequirements.lockが特徴的です。
3.7 uv
はじめはパッケージの依存解決が高速な仮想環境管理ツールでした。
やがてPythonプロジェクト管理ツールとして機能が追加されRyeと同様にオールインワンツールとなり、Ryeの後継プロジェクトに位置しています。
仮想環境管理
プロジェクトを作成します。
## プロジェクト作成
ubuntu@x:~$ uv init project
Initialized project `project` at `/home/ubuntu/project`
ubuntu@x:~$ cd project/
ubuntu@x:~/project$ ls
README.md main.py pyproject.toml
## バージョン指定
ubuntu@x:~/project$ uv python pin 3.12
Pinned `.python-version` to `3.12`
ubuntu@x:~/project$ cat .python-version
3.12
## venv作成 初回実行で.venvが作成されます。
ubuntu@x:~/project$ uv run python
Using CPython 3.12.12
Creating virtual environment at: .venv
Python 3.12.12 (main, Dec 9 2025, 19:02:36) [Clang 21.1.4 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
ubuntu@x:~/project$ ls -a
. .. .python-version .venv README.md main.py pyproject.toml uv.lock
だいたい、Ryeと同じですね。
ここまでくるとやり方が収斂してきています。
ディレクトリ構成
形自体は見慣れたvenvです。
$HOME/
└── project/
├── .venv/ # プロジェクト内
│ ├── bin/
│ │ └── python3
│ └── lib/
│ └── python3.11/
│ └── site-packages/
├── pyproject.toml
├── uv.lock
└── main.py
パッケージ管理
pyproject.toml 初期状態
[project]
name = "project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
他のツールより簡素です。
必要になってからセクションを追加する方針なのでしょう。
scipyを追加します。
shell-session
ubuntu@x:~/project$ uv add scipy
Resolved 3 packages in 982ms
Prepared 2 packages in 1m 02s
Installed 2 packages in 55ms
+ numpy==2.3.5
+ scipy==1.16.3
pyproject.toml 追加分
dependencies = [
"scipy>=1.16.3",
]
pyproject.tomlは見慣れたものです。
uv.lock は特徴的です。
uv.lock 抜粋
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "numpy"
version = "2.3.5"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/76/65/21b3bc86aac7b8f2862db1e808f1ea22b028e30a225a34a5ede9bf8678f2/numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0", size = 20584950, upload-time = "2025-11-16T22:52:42.067Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/44/37/e669fe6cbb2b96c62f6bbedc6a81c0f3b7362f6a59230b23caa673a85721/numpy-2.3.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:74ae7b798248fe62021dbf3c914245ad45d1a6b0cb4a29ecb4b31d0bfbc4cc3e", size = 16733873, upload-time = "2025-11-16T22:49:49.84Z" },
...省略
]
[[package]]
name = "project"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "scipy" },
]
[package.metadata]
requires-dist = [{ name = "scipy", specifier = ">=1.16.3" }]
[[package]]
name = "scipy"
version = "1.16.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "numpy" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0a/ca/d8ace4f98322d01abcd52d381134344bf7b431eba7ed8b42bdea5a3c2ac9/scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb", size = 30597883, upload-time = "2025-10-28T17:38:54.068Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/40/41/5bf55c3f386b1643812f3a5674edf74b26184378ef0f3e7c7a09a7e2ca7f/scipy-1.16.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:81fc5827606858cf71446a5e98715ba0e11f0dbc83d71c7409d05486592a45d6", size = 36659043, upload-time = "2025-10-28T17:32:40.285Z" },
...省略
]
uv.lock 全文
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "numpy"
version = "2.3.5"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/76/65/21b3bc86aac7b8f2862db1e808f1ea22b028e30a225a34a5ede9bf8678f2/numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0", size = 20584950, upload-time = "2025-11-16T22:52:42.067Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/44/37/e669fe6cbb2b96c62f6bbedc6a81c0f3b7362f6a59230b23caa673a85721/numpy-2.3.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:74ae7b798248fe62021dbf3c914245ad45d1a6b0cb4a29ecb4b31d0bfbc4cc3e", size = 16733873, upload-time = "2025-11-16T22:49:49.84Z" },
{ url = "https://files.pythonhosted.org/packages/c5/65/df0db6c097892c9380851ab9e44b52d4f7ba576b833996e0080181c0c439/numpy-2.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee3888d9ff7c14604052b2ca5535a30216aa0a58e948cdd3eeb8d3415f638769", size = 12259838, upload-time = "2025-11-16T22:49:52.863Z" },
{ url = "https://files.pythonhosted.org/packages/5b/e1/1ee06e70eb2136797abe847d386e7c0e830b67ad1d43f364dd04fa50d338/numpy-2.3.5-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:612a95a17655e213502f60cfb9bf9408efdc9eb1d5f50535cc6eb365d11b42b5", size = 5088378, upload-time = "2025-11-16T22:49:55.055Z" },
{ url = "https://files.pythonhosted.org/packages/6d/9c/1ca85fb86708724275103b81ec4cf1ac1d08f465368acfc8da7ab545bdae/numpy-2.3.5-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3101e5177d114a593d79dd79658650fe28b5a0d8abeb8ce6f437c0e6df5be1a4", size = 6628559, upload-time = "2025-11-16T22:49:57.371Z" },
{ url = "https://files.pythonhosted.org/packages/74/78/fcd41e5a0ce4f3f7b003da85825acddae6d7ecb60cf25194741b036ca7d6/numpy-2.3.5-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b973c57ff8e184109db042c842423ff4f60446239bd585a5131cc47f06f789d", size = 14250702, upload-time = "2025-11-16T22:49:59.632Z" },
{ url = "https://files.pythonhosted.org/packages/b6/23/2a1b231b8ff672b4c450dac27164a8b2ca7d9b7144f9c02d2396518352eb/numpy-2.3.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d8163f43acde9a73c2a33605353a4f1bc4798745a8b1d73183b28e5b435ae28", size = 16606086, upload-time = "2025-11-16T22:50:02.127Z" },
{ url = "https://files.pythonhosted.org/packages/a0/c5/5ad26fbfbe2012e190cc7d5003e4d874b88bb18861d0829edc140a713021/numpy-2.3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:51c1e14eb1e154ebd80e860722f9e6ed6ec89714ad2db2d3aa33c31d7c12179b", size = 16025985, upload-time = "2025-11-16T22:50:04.536Z" },
{ url = "https://files.pythonhosted.org/packages/d2/fa/dd48e225c46c819288148d9d060b047fd2a6fb1eb37eae25112ee4cb4453/numpy-2.3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b46b4ec24f7293f23adcd2d146960559aaf8020213de8ad1909dba6c013bf89c", size = 18542976, upload-time = "2025-11-16T22:50:07.557Z" },
{ url = "https://files.pythonhosted.org/packages/05/79/ccbd23a75862d95af03d28b5c6901a1b7da4803181513d52f3b86ed9446e/numpy-2.3.5-cp312-cp312-win32.whl", hash = "sha256:3997b5b3c9a771e157f9aae01dd579ee35ad7109be18db0e85dbdbe1de06e952", size = 6285274, upload-time = "2025-11-16T22:50:10.746Z" },
{ url = "https://files.pythonhosted.org/packages/2d/57/8aeaf160312f7f489dea47ab61e430b5cb051f59a98ae68b7133ce8fa06a/numpy-2.3.5-cp312-cp312-win_amd64.whl", hash = "sha256:86945f2ee6d10cdfd67bcb4069c1662dd711f7e2a4343db5cecec06b87cf31aa", size = 12782922, upload-time = "2025-11-16T22:50:12.811Z" },
{ url = "https://files.pythonhosted.org/packages/78/a6/aae5cc2ca78c45e64b9ef22f089141d661516856cf7c8a54ba434576900d/numpy-2.3.5-cp312-cp312-win_arm64.whl", hash = "sha256:f28620fe26bee16243be2b7b874da327312240a7cdc38b769a697578d2100013", size = 10194667, upload-time = "2025-11-16T22:50:16.16Z" },
{ url = "https://files.pythonhosted.org/packages/db/69/9cde09f36da4b5a505341180a3f2e6fadc352fd4d2b7096ce9778db83f1a/numpy-2.3.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff", size = 16728251, upload-time = "2025-11-16T22:50:19.013Z" },
{ url = "https://files.pythonhosted.org/packages/79/fb/f505c95ceddd7027347b067689db71ca80bd5ecc926f913f1a23e65cf09b/numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188", size = 12254652, upload-time = "2025-11-16T22:50:21.487Z" },
{ url = "https://files.pythonhosted.org/packages/78/da/8c7738060ca9c31b30e9301ee0cf6c5ffdbf889d9593285a1cead337f9a5/numpy-2.3.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0", size = 5083172, upload-time = "2025-11-16T22:50:24.562Z" },
{ url = "https://files.pythonhosted.org/packages/a4/b4/ee5bb2537fb9430fd2ef30a616c3672b991a4129bb1c7dcc42aa0abbe5d7/numpy-2.3.5-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:afaffc4393205524af9dfa400fa250143a6c3bc646c08c9f5e25a9f4b4d6a903", size = 6622990, upload-time = "2025-11-16T22:50:26.47Z" },
{ url = "https://files.pythonhosted.org/packages/95/03/dc0723a013c7d7c19de5ef29e932c3081df1c14ba582b8b86b5de9db7f0f/numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d", size = 14248902, upload-time = "2025-11-16T22:50:28.861Z" },
{ url = "https://files.pythonhosted.org/packages/f5/10/ca162f45a102738958dcec8023062dad0cbc17d1ab99d68c4e4a6c45fb2b/numpy-2.3.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017", size = 16597430, upload-time = "2025-11-16T22:50:31.56Z" },
{ url = "https://files.pythonhosted.org/packages/2a/51/c1e29be863588db58175175f057286900b4b3327a1351e706d5e0f8dd679/numpy-2.3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed89927b86296067b4f81f108a2271d8926467a8868e554eaf370fc27fa3ccaf", size = 16024551, upload-time = "2025-11-16T22:50:34.242Z" },
{ url = "https://files.pythonhosted.org/packages/83/68/8236589d4dbb87253d28259d04d9b814ec0ecce7cb1c7fed29729f4c3a78/numpy-2.3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51c55fe3451421f3a6ef9a9c1439e82101c57a2c9eab9feb196a62b1a10b58ce", size = 18533275, upload-time = "2025-11-16T22:50:37.651Z" },
{ url = "https://files.pythonhosted.org/packages/40/56/2932d75b6f13465239e3b7b7e511be27f1b8161ca2510854f0b6e521c395/numpy-2.3.5-cp313-cp313-win32.whl", hash = "sha256:1978155dd49972084bd6ef388d66ab70f0c323ddee6f693d539376498720fb7e", size = 6277637, upload-time = "2025-11-16T22:50:40.11Z" },
{ url = "https://files.pythonhosted.org/packages/0c/88/e2eaa6cffb115b85ed7c7c87775cb8bcf0816816bc98ca8dbfa2ee33fe6e/numpy-2.3.5-cp313-cp313-win_amd64.whl", hash = "sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b", size = 12779090, upload-time = "2025-11-16T22:50:42.503Z" },
{ url = "https://files.pythonhosted.org/packages/8f/88/3f41e13a44ebd4034ee17baa384acac29ba6a4fcc2aca95f6f08ca0447d1/numpy-2.3.5-cp313-cp313-win_arm64.whl", hash = "sha256:0472f11f6ec23a74a906a00b48a4dcf3849209696dff7c189714511268d103ae", size = 10194710, upload-time = "2025-11-16T22:50:44.971Z" },
{ url = "https://files.pythonhosted.org/packages/13/cb/71744144e13389d577f867f745b7df2d8489463654a918eea2eeb166dfc9/numpy-2.3.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:414802f3b97f3c1eef41e530aaba3b3c1620649871d8cb38c6eaff034c2e16bd", size = 16827292, upload-time = "2025-11-16T22:50:47.715Z" },
{ url = "https://files.pythonhosted.org/packages/71/80/ba9dc6f2a4398e7f42b708a7fdc841bb638d353be255655498edbf9a15a8/numpy-2.3.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5ee6609ac3604fa7780e30a03e5e241a7956f8e2fcfe547d51e3afa5247ac47f", size = 12378897, upload-time = "2025-11-16T22:50:51.327Z" },
{ url = "https://files.pythonhosted.org/packages/2e/6d/db2151b9f64264bcceccd51741aa39b50150de9b602d98ecfe7e0c4bff39/numpy-2.3.5-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:86d835afea1eaa143012a2d7a3f45a3adce2d7adc8b4961f0b362214d800846a", size = 5207391, upload-time = "2025-11-16T22:50:54.542Z" },
{ url = "https://files.pythonhosted.org/packages/80/ae/429bacace5ccad48a14c4ae5332f6aa8ab9f69524193511d60ccdfdc65fa/numpy-2.3.5-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:30bc11310e8153ca664b14c5f1b73e94bd0503681fcf136a163de856f3a50139", size = 6721275, upload-time = "2025-11-16T22:50:56.794Z" },
{ url = "https://files.pythonhosted.org/packages/74/5b/1919abf32d8722646a38cd527bc3771eb229a32724ee6ba340ead9b92249/numpy-2.3.5-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1062fde1dcf469571705945b0f221b73928f34a20c904ffb45db101907c3454e", size = 14306855, upload-time = "2025-11-16T22:50:59.208Z" },
{ url = "https://files.pythonhosted.org/packages/a5/87/6831980559434973bebc30cd9c1f21e541a0f2b0c280d43d3afd909b66d0/numpy-2.3.5-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce581db493ea1a96c0556360ede6607496e8bf9b3a8efa66e06477267bc831e9", size = 16657359, upload-time = "2025-11-16T22:51:01.991Z" },
{ url = "https://files.pythonhosted.org/packages/dd/91/c797f544491ee99fd00495f12ebb7802c440c1915811d72ac5b4479a3356/numpy-2.3.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:cc8920d2ec5fa99875b670bb86ddeb21e295cb07aa331810d9e486e0b969d946", size = 16093374, upload-time = "2025-11-16T22:51:05.291Z" },
{ url = "https://files.pythonhosted.org/packages/74/a6/54da03253afcbe7a72785ec4da9c69fb7a17710141ff9ac5fcb2e32dbe64/numpy-2.3.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9ee2197ef8c4f0dfe405d835f3b6a14f5fee7782b5de51ba06fb65fc9b36e9f1", size = 18594587, upload-time = "2025-11-16T22:51:08.585Z" },
{ url = "https://files.pythonhosted.org/packages/80/e9/aff53abbdd41b0ecca94285f325aff42357c6b5abc482a3fcb4994290b18/numpy-2.3.5-cp313-cp313t-win32.whl", hash = "sha256:70b37199913c1bd300ff6e2693316c6f869c7ee16378faf10e4f5e3275b299c3", size = 6405940, upload-time = "2025-11-16T22:51:11.541Z" },
{ url = "https://files.pythonhosted.org/packages/d5/81/50613fec9d4de5480de18d4f8ef59ad7e344d497edbef3cfd80f24f98461/numpy-2.3.5-cp313-cp313t-win_amd64.whl", hash = "sha256:b501b5fa195cc9e24fe102f21ec0a44dffc231d2af79950b451e0d99cea02234", size = 12920341, upload-time = "2025-11-16T22:51:14.312Z" },
{ url = "https://files.pythonhosted.org/packages/bb/ab/08fd63b9a74303947f34f0bd7c5903b9c5532c2d287bead5bdf4c556c486/numpy-2.3.5-cp313-cp313t-win_arm64.whl", hash = "sha256:a80afd79f45f3c4a7d341f13acbe058d1ca8ac017c165d3fa0d3de6bc1a079d7", size = 10262507, upload-time = "2025-11-16T22:51:16.846Z" },
{ url = "https://files.pythonhosted.org/packages/ba/97/1a914559c19e32d6b2e233cf9a6a114e67c856d35b1d6babca571a3e880f/numpy-2.3.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:bf06bc2af43fa8d32d30fae16ad965663e966b1a3202ed407b84c989c3221e82", size = 16735706, upload-time = "2025-11-16T22:51:19.558Z" },
{ url = "https://files.pythonhosted.org/packages/57/d4/51233b1c1b13ecd796311216ae417796b88b0616cfd8a33ae4536330748a/numpy-2.3.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:052e8c42e0c49d2575621c158934920524f6c5da05a1d3b9bab5d8e259e045f0", size = 12264507, upload-time = "2025-11-16T22:51:22.492Z" },
{ url = "https://files.pythonhosted.org/packages/45/98/2fe46c5c2675b8306d0b4a3ec3494273e93e1226a490f766e84298576956/numpy-2.3.5-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:1ed1ec893cff7040a02c8aa1c8611b94d395590d553f6b53629a4461dc7f7b63", size = 5093049, upload-time = "2025-11-16T22:51:25.171Z" },
{ url = "https://files.pythonhosted.org/packages/ce/0e/0698378989bb0ac5f1660c81c78ab1fe5476c1a521ca9ee9d0710ce54099/numpy-2.3.5-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:2dcd0808a421a482a080f89859a18beb0b3d1e905b81e617a188bd80422d62e9", size = 6626603, upload-time = "2025-11-16T22:51:27Z" },
{ url = "https://files.pythonhosted.org/packages/5e/a6/9ca0eecc489640615642a6cbc0ca9e10df70df38c4d43f5a928ff18d8827/numpy-2.3.5-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:727fd05b57df37dc0bcf1a27767a3d9a78cbbc92822445f32cc3436ba797337b", size = 14262696, upload-time = "2025-11-16T22:51:29.402Z" },
{ url = "https://files.pythonhosted.org/packages/c8/f6/07ec185b90ec9d7217a00eeeed7383b73d7e709dae2a9a021b051542a708/numpy-2.3.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520", size = 16597350, upload-time = "2025-11-16T22:51:32.167Z" },
{ url = "https://files.pythonhosted.org/packages/75/37/164071d1dde6a1a84c9b8e5b414fa127981bad47adf3a6b7e23917e52190/numpy-2.3.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8f7f0e05112916223d3f438f293abf0727e1181b5983f413dfa2fefc4098245c", size = 16040190, upload-time = "2025-11-16T22:51:35.403Z" },
{ url = "https://files.pythonhosted.org/packages/08/3c/f18b82a406b04859eb026d204e4e1773eb41c5be58410f41ffa511d114ae/numpy-2.3.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2e2eb32ddb9ccb817d620ac1d8dae7c3f641c1e5f55f531a33e8ab97960a75b8", size = 18536749, upload-time = "2025-11-16T22:51:39.698Z" },
{ url = "https://files.pythonhosted.org/packages/40/79/f82f572bf44cf0023a2fe8588768e23e1592585020d638999f15158609e1/numpy-2.3.5-cp314-cp314-win32.whl", hash = "sha256:66f85ce62c70b843bab1fb14a05d5737741e74e28c7b8b5a064de10142fad248", size = 6335432, upload-time = "2025-11-16T22:51:42.476Z" },
{ url = "https://files.pythonhosted.org/packages/a3/2e/235b4d96619931192c91660805e5e49242389742a7a82c27665021db690c/numpy-2.3.5-cp314-cp314-win_amd64.whl", hash = "sha256:e6a0bc88393d65807d751a614207b7129a310ca4fe76a74e5c7da5fa5671417e", size = 12919388, upload-time = "2025-11-16T22:51:45.275Z" },
{ url = "https://files.pythonhosted.org/packages/07/2b/29fd75ce45d22a39c61aad74f3d718e7ab67ccf839ca8b60866054eb15f8/numpy-2.3.5-cp314-cp314-win_arm64.whl", hash = "sha256:aeffcab3d4b43712bb7a60b65f6044d444e75e563ff6180af8f98dd4b905dfd2", size = 10476651, upload-time = "2025-11-16T22:51:47.749Z" },
{ url = "https://files.pythonhosted.org/packages/17/e1/f6a721234ebd4d87084cfa68d081bcba2f5cfe1974f7de4e0e8b9b2a2ba1/numpy-2.3.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:17531366a2e3a9e30762c000f2c43a9aaa05728712e25c11ce1dbe700c53ad41", size = 16834503, upload-time = "2025-11-16T22:51:50.443Z" },
{ url = "https://files.pythonhosted.org/packages/5c/1c/baf7ffdc3af9c356e1c135e57ab7cf8d247931b9554f55c467efe2c69eff/numpy-2.3.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d21644de1b609825ede2f48be98dfde4656aefc713654eeee280e37cadc4e0ad", size = 12381612, upload-time = "2025-11-16T22:51:53.609Z" },
{ url = "https://files.pythonhosted.org/packages/74/91/f7f0295151407ddc9ba34e699013c32c3c91944f9b35fcf9281163dc1468/numpy-2.3.5-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:c804e3a5aba5460c73955c955bdbd5c08c354954e9270a2c1565f62e866bdc39", size = 5210042, upload-time = "2025-11-16T22:51:56.213Z" },
{ url = "https://files.pythonhosted.org/packages/2e/3b/78aebf345104ec50dd50a4d06ddeb46a9ff5261c33bcc58b1c4f12f85ec2/numpy-2.3.5-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:cc0a57f895b96ec78969c34f682c602bf8da1a0270b09bc65673df2e7638ec20", size = 6724502, upload-time = "2025-11-16T22:51:58.584Z" },
{ url = "https://files.pythonhosted.org/packages/02/c6/7c34b528740512e57ef1b7c8337ab0b4f0bddf34c723b8996c675bc2bc91/numpy-2.3.5-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:900218e456384ea676e24ea6a0417f030a3b07306d29d7ad843957b40a9d8d52", size = 14308962, upload-time = "2025-11-16T22:52:01.698Z" },
{ url = "https://files.pythonhosted.org/packages/80/35/09d433c5262bc32d725bafc619e095b6a6651caf94027a03da624146f655/numpy-2.3.5-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09a1bea522b25109bf8e6f3027bd810f7c1085c64a0c7ce050c1676ad0ba010b", size = 16655054, upload-time = "2025-11-16T22:52:04.267Z" },
{ url = "https://files.pythonhosted.org/packages/7a/ab/6a7b259703c09a88804fa2430b43d6457b692378f6b74b356155283566ac/numpy-2.3.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:04822c00b5fd0323c8166d66c701dc31b7fbd252c100acd708c48f763968d6a3", size = 16091613, upload-time = "2025-11-16T22:52:08.651Z" },
{ url = "https://files.pythonhosted.org/packages/c2/88/330da2071e8771e60d1038166ff9d73f29da37b01ec3eb43cb1427464e10/numpy-2.3.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d6889ec4ec662a1a37eb4b4fb26b6100841804dac55bd9df579e326cdc146227", size = 18591147, upload-time = "2025-11-16T22:52:11.453Z" },
{ url = "https://files.pythonhosted.org/packages/51/41/851c4b4082402d9ea860c3626db5d5df47164a712cb23b54be028b184c1c/numpy-2.3.5-cp314-cp314t-win32.whl", hash = "sha256:93eebbcf1aafdf7e2ddd44c2923e2672e1010bddc014138b229e49725b4d6be5", size = 6479806, upload-time = "2025-11-16T22:52:14.641Z" },
{ url = "https://files.pythonhosted.org/packages/90/30/d48bde1dfd93332fa557cff1972fbc039e055a52021fbef4c2c4b1eefd17/numpy-2.3.5-cp314-cp314t-win_amd64.whl", hash = "sha256:c8a9958e88b65c3b27e22ca2a076311636850b612d6bbfb76e8d156aacde2aaf", size = 13105760, upload-time = "2025-11-16T22:52:17.975Z" },
{ url = "https://files.pythonhosted.org/packages/2d/fd/4b5eb0b3e888d86aee4d198c23acec7d214baaf17ea93c1adec94c9518b9/numpy-2.3.5-cp314-cp314t-win_arm64.whl", hash = "sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42", size = 10545459, upload-time = "2025-11-16T22:52:20.55Z" },
]
[[package]]
name = "project"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "scipy" },
]
[package.metadata]
requires-dist = [{ name = "scipy", specifier = ">=1.16.3" }]
[[package]]
name = "scipy"
version = "1.16.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "numpy" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0a/ca/d8ace4f98322d01abcd52d381134344bf7b431eba7ed8b42bdea5a3c2ac9/scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb", size = 30597883, upload-time = "2025-10-28T17:38:54.068Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/40/41/5bf55c3f386b1643812f3a5674edf74b26184378ef0f3e7c7a09a7e2ca7f/scipy-1.16.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:81fc5827606858cf71446a5e98715ba0e11f0dbc83d71c7409d05486592a45d6", size = 36659043, upload-time = "2025-10-28T17:32:40.285Z" },
{ url = "https://files.pythonhosted.org/packages/1e/0f/65582071948cfc45d43e9870bf7ca5f0e0684e165d7c9ef4e50d783073eb/scipy-1.16.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:c97176013d404c7346bf57874eaac5187d969293bf40497140b0a2b2b7482e07", size = 28898986, upload-time = "2025-10-28T17:32:45.325Z" },
{ url = "https://files.pythonhosted.org/packages/96/5e/36bf3f0ac298187d1ceadde9051177d6a4fe4d507e8f59067dc9dd39e650/scipy-1.16.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2b71d93c8a9936046866acebc915e2af2e292b883ed6e2cbe5c34beb094b82d9", size = 20889814, upload-time = "2025-10-28T17:32:49.277Z" },
{ url = "https://files.pythonhosted.org/packages/80/35/178d9d0c35394d5d5211bbff7ac4f2986c5488b59506fef9e1de13ea28d3/scipy-1.16.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3d4a07a8e785d80289dfe66b7c27d8634a773020742ec7187b85ccc4b0e7b686", size = 23565795, upload-time = "2025-10-28T17:32:53.337Z" },
{ url = "https://files.pythonhosted.org/packages/fa/46/d1146ff536d034d02f83c8afc3c4bab2eddb634624d6529a8512f3afc9da/scipy-1.16.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0553371015692a898e1aa858fed67a3576c34edefa6b7ebdb4e9dde49ce5c203", size = 33349476, upload-time = "2025-10-28T17:32:58.353Z" },
{ url = "https://files.pythonhosted.org/packages/79/2e/415119c9ab3e62249e18c2b082c07aff907a273741b3f8160414b0e9193c/scipy-1.16.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:72d1717fd3b5e6ec747327ce9bda32d5463f472c9dce9f54499e81fbd50245a1", size = 35676692, upload-time = "2025-10-28T17:33:03.88Z" },
{ url = "https://files.pythonhosted.org/packages/27/82/df26e44da78bf8d2aeaf7566082260cfa15955a5a6e96e6a29935b64132f/scipy-1.16.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fb2472e72e24d1530debe6ae078db70fb1605350c88a3d14bc401d6306dbffe", size = 36019345, upload-time = "2025-10-28T17:33:09.773Z" },
{ url = "https://files.pythonhosted.org/packages/82/31/006cbb4b648ba379a95c87262c2855cd0d09453e500937f78b30f02fa1cd/scipy-1.16.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c5192722cffe15f9329a3948c4b1db789fbb1f05c97899187dcf009b283aea70", size = 38678975, upload-time = "2025-10-28T17:33:15.809Z" },
{ url = "https://files.pythonhosted.org/packages/c2/7f/acbd28c97e990b421af7d6d6cd416358c9c293fc958b8529e0bd5d2a2a19/scipy-1.16.3-cp312-cp312-win_amd64.whl", hash = "sha256:56edc65510d1331dae01ef9b658d428e33ed48b4f77b1d51caf479a0253f96dc", size = 38555926, upload-time = "2025-10-28T17:33:21.388Z" },
{ url = "https://files.pythonhosted.org/packages/ce/69/c5c7807fd007dad4f48e0a5f2153038dc96e8725d3345b9ee31b2b7bed46/scipy-1.16.3-cp312-cp312-win_arm64.whl", hash = "sha256:a8a26c78ef223d3e30920ef759e25625a0ecdd0d60e5a8818b7513c3e5384cf2", size = 25463014, upload-time = "2025-10-28T17:33:25.975Z" },
{ url = "https://files.pythonhosted.org/packages/72/f1/57e8327ab1508272029e27eeef34f2302ffc156b69e7e233e906c2a5c379/scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c", size = 36617856, upload-time = "2025-10-28T17:33:31.375Z" },
{ url = "https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d", size = 28874306, upload-time = "2025-10-28T17:33:36.516Z" },
{ url = "https://files.pythonhosted.org/packages/15/65/3a9400efd0228a176e6ec3454b1fa998fbbb5a8defa1672c3f65706987db/scipy-1.16.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:5803c5fadd29de0cf27fa08ccbfe7a9e5d741bf63e4ab1085437266f12460ff9", size = 20865371, upload-time = "2025-10-28T17:33:42.094Z" },
{ url = "https://files.pythonhosted.org/packages/33/d7/eda09adf009a9fb81827194d4dd02d2e4bc752cef16737cc4ef065234031/scipy-1.16.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:b81c27fc41954319a943d43b20e07c40bdcd3ff7cf013f4fb86286faefe546c4", size = 23524877, upload-time = "2025-10-28T17:33:48.483Z" },
{ url = "https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959", size = 33342103, upload-time = "2025-10-28T17:33:56.495Z" },
{ url = "https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88", size = 35697297, upload-time = "2025-10-28T17:34:04.722Z" },
{ url = "https://files.pythonhosted.org/packages/04/e1/6496dadbc80d8d896ff72511ecfe2316b50313bfc3ebf07a3f580f08bd8c/scipy-1.16.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:663b8d66a8748051c3ee9c96465fb417509315b99c71550fda2591d7dd634234", size = 36021756, upload-time = "2025-10-28T17:34:13.482Z" },
{ url = "https://files.pythonhosted.org/packages/fe/bd/a8c7799e0136b987bda3e1b23d155bcb31aec68a4a472554df5f0937eef7/scipy-1.16.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eab43fae33a0c39006a88096cd7b4f4ef545ea0447d250d5ac18202d40b6611d", size = 38696566, upload-time = "2025-10-28T17:34:22.384Z" },
{ url = "https://files.pythonhosted.org/packages/cd/01/1204382461fcbfeb05b6161b594f4007e78b6eba9b375382f79153172b4d/scipy-1.16.3-cp313-cp313-win_amd64.whl", hash = "sha256:062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304", size = 38529877, upload-time = "2025-10-28T17:35:51.076Z" },
{ url = "https://files.pythonhosted.org/packages/7f/14/9d9fbcaa1260a94f4bb5b64ba9213ceb5d03cd88841fe9fd1ffd47a45b73/scipy-1.16.3-cp313-cp313-win_arm64.whl", hash = "sha256:50a3dbf286dbc7d84f176f9a1574c705f277cb6565069f88f60db9eafdbe3ee2", size = 25455366, upload-time = "2025-10-28T17:35:59.014Z" },
{ url = "https://files.pythonhosted.org/packages/e2/a3/9ec205bd49f42d45d77f1730dbad9ccf146244c1647605cf834b3a8c4f36/scipy-1.16.3-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:fb4b29f4cf8cc5a8d628bc8d8e26d12d7278cd1f219f22698a378c3d67db5e4b", size = 37027931, upload-time = "2025-10-28T17:34:31.451Z" },
{ url = "https://files.pythonhosted.org/packages/25/06/ca9fd1f3a4589cbd825b1447e5db3a8ebb969c1eaf22c8579bd286f51b6d/scipy-1.16.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:8d09d72dc92742988b0e7750bddb8060b0c7079606c0d24a8cc8e9c9c11f9079", size = 29400081, upload-time = "2025-10-28T17:34:39.087Z" },
{ url = "https://files.pythonhosted.org/packages/6a/56/933e68210d92657d93fb0e381683bc0e53a965048d7358ff5fbf9e6a1b17/scipy-1.16.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:03192a35e661470197556de24e7cb1330d84b35b94ead65c46ad6f16f6b28f2a", size = 21391244, upload-time = "2025-10-28T17:34:45.234Z" },
{ url = "https://files.pythonhosted.org/packages/a8/7e/779845db03dc1418e215726329674b40576879b91814568757ff0014ad65/scipy-1.16.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:57d01cb6f85e34f0946b33caa66e892aae072b64b034183f3d87c4025802a119", size = 23929753, upload-time = "2025-10-28T17:34:51.793Z" },
{ url = "https://files.pythonhosted.org/packages/4c/4b/f756cf8161d5365dcdef9e5f460ab226c068211030a175d2fc7f3f41ca64/scipy-1.16.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:96491a6a54e995f00a28a3c3badfff58fd093bf26cd5fb34a2188c8c756a3a2c", size = 33496912, upload-time = "2025-10-28T17:34:59.8Z" },
{ url = "https://files.pythonhosted.org/packages/09/b5/222b1e49a58668f23839ca1542a6322bb095ab8d6590d4f71723869a6c2c/scipy-1.16.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cd13e354df9938598af2be05822c323e97132d5e6306b83a3b4ee6724c6e522e", size = 35802371, upload-time = "2025-10-28T17:35:08.173Z" },
{ url = "https://files.pythonhosted.org/packages/c1/8d/5964ef68bb31829bde27611f8c9deeac13764589fe74a75390242b64ca44/scipy-1.16.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:63d3cdacb8a824a295191a723ee5e4ea7768ca5ca5f2838532d9f2e2b3ce2135", size = 36190477, upload-time = "2025-10-28T17:35:16.7Z" },
{ url = "https://files.pythonhosted.org/packages/ab/f2/b31d75cb9b5fa4dd39a0a931ee9b33e7f6f36f23be5ef560bf72e0f92f32/scipy-1.16.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e7efa2681ea410b10dde31a52b18b0154d66f2485328830e45fdf183af5aefc6", size = 38796678, upload-time = "2025-10-28T17:35:26.354Z" },
{ url = "https://files.pythonhosted.org/packages/b4/1e/b3723d8ff64ab548c38d87055483714fefe6ee20e0189b62352b5e015bb1/scipy-1.16.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2d1ae2cf0c350e7705168ff2429962a89ad90c2d49d1dd300686d8b2a5af22fc", size = 38640178, upload-time = "2025-10-28T17:35:35.304Z" },
{ url = "https://files.pythonhosted.org/packages/8e/f3/d854ff38789aca9b0cc23008d607ced9de4f7ab14fa1ca4329f86b3758ca/scipy-1.16.3-cp313-cp313t-win_arm64.whl", hash = "sha256:0c623a54f7b79dd88ef56da19bc2873afec9673a48f3b85b18e4d402bdd29a5a", size = 25803246, upload-time = "2025-10-28T17:35:42.155Z" },
{ url = "https://files.pythonhosted.org/packages/99/f6/99b10fd70f2d864c1e29a28bbcaa0c6340f9d8518396542d9ea3b4aaae15/scipy-1.16.3-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:875555ce62743e1d54f06cdf22c1e0bc47b91130ac40fe5d783b6dfa114beeb6", size = 36606469, upload-time = "2025-10-28T17:36:08.741Z" },
{ url = "https://files.pythonhosted.org/packages/4d/74/043b54f2319f48ea940dd025779fa28ee360e6b95acb7cd188fad4391c6b/scipy-1.16.3-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:bb61878c18a470021fb515a843dc7a76961a8daceaaaa8bad1332f1bf4b54657", size = 28872043, upload-time = "2025-10-28T17:36:16.599Z" },
{ url = "https://files.pythonhosted.org/packages/4d/e1/24b7e50cc1c4ee6ffbcb1f27fe9f4c8b40e7911675f6d2d20955f41c6348/scipy-1.16.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2622206f5559784fa5c4b53a950c3c7c1cf3e84ca1b9c4b6c03f062f289ca26", size = 20862952, upload-time = "2025-10-28T17:36:22.966Z" },
{ url = "https://files.pythonhosted.org/packages/dd/3a/3e8c01a4d742b730df368e063787c6808597ccb38636ed821d10b39ca51b/scipy-1.16.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7f68154688c515cdb541a31ef8eb66d8cd1050605be9dcd74199cbd22ac739bc", size = 23508512, upload-time = "2025-10-28T17:36:29.731Z" },
{ url = "https://files.pythonhosted.org/packages/1f/60/c45a12b98ad591536bfe5330cb3cfe1850d7570259303563b1721564d458/scipy-1.16.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3c820ddb80029fe9f43d61b81d8b488d3ef8ca010d15122b152db77dc94c22", size = 33413639, upload-time = "2025-10-28T17:36:37.982Z" },
{ url = "https://files.pythonhosted.org/packages/71/bc/35957d88645476307e4839712642896689df442f3e53b0fa016ecf8a3357/scipy-1.16.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3837938ae715fc0fe3c39c0202de3a8853aff22ca66781ddc2ade7554b7e2cc", size = 35704729, upload-time = "2025-10-28T17:36:46.547Z" },
{ url = "https://files.pythonhosted.org/packages/3b/15/89105e659041b1ca11c386e9995aefacd513a78493656e57789f9d9eab61/scipy-1.16.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aadd23f98f9cb069b3bd64ddc900c4d277778242e961751f77a8cb5c4b946fb0", size = 36086251, upload-time = "2025-10-28T17:36:55.161Z" },
{ url = "https://files.pythonhosted.org/packages/1a/87/c0ea673ac9c6cc50b3da2196d860273bc7389aa69b64efa8493bdd25b093/scipy-1.16.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b7c5f1bda1354d6a19bc6af73a649f8285ca63ac6b52e64e658a5a11d4d69800", size = 38716681, upload-time = "2025-10-28T17:37:04.1Z" },
{ url = "https://files.pythonhosted.org/packages/91/06/837893227b043fb9b0d13e4bd7586982d8136cb249ffb3492930dab905b8/scipy-1.16.3-cp314-cp314-win_amd64.whl", hash = "sha256:e5d42a9472e7579e473879a1990327830493a7047506d58d73fc429b84c1d49d", size = 39358423, upload-time = "2025-10-28T17:38:20.005Z" },
{ url = "https://files.pythonhosted.org/packages/95/03/28bce0355e4d34a7c034727505a02d19548549e190bedd13a721e35380b7/scipy-1.16.3-cp314-cp314-win_arm64.whl", hash = "sha256:6020470b9d00245926f2d5bb93b119ca0340f0d564eb6fbaad843eaebf9d690f", size = 26135027, upload-time = "2025-10-28T17:38:24.966Z" },
{ url = "https://files.pythonhosted.org/packages/b2/6f/69f1e2b682efe9de8fe9f91040f0cd32f13cfccba690512ba4c582b0bc29/scipy-1.16.3-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:e1d27cbcb4602680a49d787d90664fa4974063ac9d4134813332a8c53dbe667c", size = 37028379, upload-time = "2025-10-28T17:37:14.061Z" },
{ url = "https://files.pythonhosted.org/packages/7c/2d/e826f31624a5ebbab1cd93d30fd74349914753076ed0593e1d56a98c4fb4/scipy-1.16.3-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9b9c9c07b6d56a35777a1b4cc8966118fb16cfd8daf6743867d17d36cfad2d40", size = 29400052, upload-time = "2025-10-28T17:37:21.709Z" },
{ url = "https://files.pythonhosted.org/packages/69/27/d24feb80155f41fd1f156bf144e7e049b4e2b9dd06261a242905e3bc7a03/scipy-1.16.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:3a4c460301fb2cffb7f88528f30b3127742cff583603aa7dc964a52c463b385d", size = 21391183, upload-time = "2025-10-28T17:37:29.559Z" },
{ url = "https://files.pythonhosted.org/packages/f8/d3/1b229e433074c5738a24277eca520a2319aac7465eea7310ea6ae0e98ae2/scipy-1.16.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:f667a4542cc8917af1db06366d3f78a5c8e83badd56409f94d1eac8d8d9133fa", size = 23930174, upload-time = "2025-10-28T17:37:36.306Z" },
{ url = "https://files.pythonhosted.org/packages/16/9d/d9e148b0ec680c0f042581a2be79a28a7ab66c0c4946697f9e7553ead337/scipy-1.16.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f379b54b77a597aa7ee5e697df0d66903e41b9c85a6dd7946159e356319158e8", size = 33497852, upload-time = "2025-10-28T17:37:42.228Z" },
{ url = "https://files.pythonhosted.org/packages/2f/22/4e5f7561e4f98b7bea63cf3fd7934bff1e3182e9f1626b089a679914d5c8/scipy-1.16.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4aff59800a3b7f786b70bfd6ab551001cb553244988d7d6b8299cb1ea653b353", size = 35798595, upload-time = "2025-10-28T17:37:48.102Z" },
{ url = "https://files.pythonhosted.org/packages/83/42/6644d714c179429fc7196857866f219fef25238319b650bb32dde7bf7a48/scipy-1.16.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:da7763f55885045036fabcebd80144b757d3db06ab0861415d1c3b7c69042146", size = 36186269, upload-time = "2025-10-28T17:37:53.72Z" },
{ url = "https://files.pythonhosted.org/packages/ac/70/64b4d7ca92f9cf2e6fc6aaa2eecf80bb9b6b985043a9583f32f8177ea122/scipy-1.16.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d", size = 38802779, upload-time = "2025-10-28T17:37:59.393Z" },
{ url = "https://files.pythonhosted.org/packages/61/82/8d0e39f62764cce5ffd5284131e109f07cf8955aef9ab8ed4e3aa5e30539/scipy-1.16.3-cp314-cp314t-win_amd64.whl", hash = "sha256:d9f48cafc7ce94cf9b15c6bffdc443a81a27bf7075cf2dcd5c8b40f85d10c4e7", size = 39471128, upload-time = "2025-10-28T17:38:05.259Z" },
{ url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" },
]
ハッシュのみであったりハッシュ+名前のロックファイルのパターンはありましたが、uvが一番情報量が多いです。
それぞれの用途は未調査のため、次へ進みます。
依存解決
アルゴリズムはPoetryでも挙げたPubGrubを使用しています。これで探索が速いらしい。
加えて、ネットワーク的な最適化としてwheelファイルを全てダウンロードせずにメタデータだけを取り出したりもしています。
Pythonだと難しい並列化がRustによってやりやすくなっているというのもあります。
dev/prod分離
Part 3 をはじめから見てきたならば、もう予想できると思います。
$ uv add pytest --dev
$ uv sync # すべてインストール
$ uv sync --no-dev # 本番環境用
pyproject.toml追加分
[dependency-groups]
dev = [
"pytest>=9.0.2",
]
uv pip
もともとpipの代替のため uv pip コマンドがあります。
よく「uv add と uv pip どちらを使うべきか?」という話になります。
基本的にプロジェクト単位で開発をするなら uv add を使います。pyproject.tomlとuv.lockが更新されます。
pip installなどpipを使っていたワークフローでそのまま uv を導入する場合は uv pip を使います。高速化の効果があります。
また、uv pip compile pyproject.toml -o requirements.txt で pip で使える requirements.txt を生成できます。
Ryeは内部でこれを使っています。
まとめ
uvは高速でRyeの後継にふさわしく開発全体の操作ができます。
速さと機能で2025年時点で最高のツールとなっています。
ただし、Part 5で触れますが、タスクランナー機能はありません。
3.8 Anaconda
環境中心の設計で、Pythonバージョンも含めて完全に独立した環境を作成します。environment.ymlで依存関係を管理し、conda list --explicitでロックファイルを生成できます。
独自リポジトリでバイナリ配布を行い、C/C++ライブラリも含めて管理します。
3.9 まとめ
venv + pip-tools は基本ツールの組み合わせです。モダンな開発方法のために手順が多くなります。
Pipenvはツールの使い分けを減らして、現在主流になっている単一の設定ファイルとロックファイルでプロジェクトを管理する方法を示しました。しかし、現在はPython標準となったpyproject.tomlから離れた存在です。
Poetryはpyproject.tomlに準拠し、依存解決の改善とパッケージ公開が統合され完成形に近づいたツールです。
RyeはPython Standard Buildsによる速い簡単なインストールができるバージョン管理機能も統合して開発作業全体をカバーできるツールでした。
uvはパッケージ依存解決の高速化を実現し、Ryeの後継として機能を充実させて高速で高機能なPython開発ツールとなりました。
Part 4: 📤 パッケージング・公開
これまでは「パッケージを使う側」の視点でした。 このPartでは、自分のコードをパッケージとして配布する「パッケージを作る側」の視点で、備えられている機能、コマンド、設定ファイルの関連部分を中心にツールを比較します。
詳細な手順は各ツールのドキュメントを参照してください。
4.1 比較
| ツール | wheel/sdist作成 | PyPI公開 | pyproject.toml対応 | ビルドバックエンド | 設定ファイル | 特徴 |
|---|---|---|---|---|---|---|
| setuptools + twine | ✅ | ✅ | ✅ | setuptools | setup.py / pyproject.toml | |
| Poetry | ✅ | ✅ | ✅ | poetry-core | pyproject.toml | パッケージ管理オールインワン |
| Rye | ✅ | ✅ | ✅ | 選択可能 | pyproject.toml | オールインワン |
| uv | ✅ | ✅ | ✅ | 選択可能 | pyproject.toml | 高速・オールインワン |
| Anaconda | ✅ | ✅ | ❌ | - | meta.yaml | 独自エコシステム |
setuptools + twine は伝統的な標準ツールです。
Poetry は依存関係管理とパッケージング・公開機能を統合したツールです。
Rye はPythonバージョン管理も含めたオールインワンツールです。
uv は高速なオールインワンツールでRyeの後継に位置しています。
Anaconda はPyPIとは独立したパッケージ体系を持ちコミュニティベースのconda-forgeへのパッケージ追加が可能です。
4.2 setuptools + twine
setuptoolsはPythonパッケージングの長年の標準ツールです。 twineはビルドしたパッケージをPyPIにアップロードするツールです。 通常、この2つをセットで使います。
従来の方式: setup.py/setup.cfg
伝統的にはsetup.pyで設定を記述していました。
setup.py
from setuptools import setup, find_packages
setup(
name="mypackage",
version="0.1.0",
author="Your Name",
author_email="you@example.com",
description="A sample Python package",
packages=find_packages(),
install_requires=[
"requests>=2.28.0",
],
python_requires=">=3.8",
)
設定がコードにあるという、古き良きCGIにありそうな方法です。
また、setup.cfgを使って設定を宣言的に記述する方法もありました。
setup.cfg
[metadata]
name = mypackage
version = 0.1.0
author = Your Name
author_email = you@example.com
description = A sample Python package
python_requires = >=3.8
[options]
packages = find:
install_requires =
requests>=2.28.0
この場合、setup.pyは最小限の記述になります。
setup.py
from setuptools import setup
setup()
pyproject.toml
PEP 517/518により、pyproject.tomlが標準化されました。
build-system セクションでsetuptoolsを指定します。
pyproject.toml
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "mypackage"
version = "0.1.0"
description = "A sample Python package"
authors = [
{name = "Your Name", email = "you@example.com"}
]
requires-python = ">=3.8"
dependencies = [
"requests>=2.28.0",
]
[project.optional-dependencies]
dev = ["pytest>=7.0", "black>=22.0"]
ビルドと公開
buildモジュールでパッケージをビルドします。
$ python -m build
* Creating isolated environment: venv+pip...
* Building wheel...
Successfully built mypackage-0.1.0-py3-none-any.whl and mypackage-0.1.0.tar.gz
$ ls dist/
mypackage-0.1.0-py3-none-any.whl
mypackage-0.1.0.tar.gz
twineでアップロードします。
# TestPyPIで動作確認
$ twine upload --repository testpypi dist/*
Uploading distributions to https://test.pypi.org/legacy/
Enter your username: __token__
Enter your password: pypi-...
Uploading mypackage-0.1.0-py3-none-any.whl
Uploading mypackage-0.1.0.tar.gz
# 本番PyPIに公開
$ twine upload dist/*
明示的にdist/*を指定したりまあまあ注意を要する作業です。
特徴
現在は設定をpyproject.tomlで管理できますが操作に注意が必要です。
4.3 Poetry
PoetryはPart 3で触れたように、依存関係管理からパッケージング、公開まで統合したツールです。
ビルド・パッケージングと配布用のコマンドが備えられています。優しい!
$ poetry build # ビルド
$ poetry publish # PyPIへのアップロード
セマンティックバージョニングに従ってpyproject.tomlのバージョン数値をインクリメントするコマンドもあったりします。
$ poetry version patch # 0.1.0 -> 0.1.1
$ poetry version minor # 0.1.1 -> 0.2.0
$ poetry version major # 0.2.0 -> 1.0.0
手で編集したらよくないかと思わなくもないですが、こういうコマンドがあるということはセマンティックバージョニングの作法に従ってほしいという意思表示と捉えることができます。
pyproject.toml
基本的には標準化されたprojectセクションに情報を置きます。
pyproject.toml
[project]
name = "mypackage"
version = "0.1.0"
description = "A sample Python package"
authors = [
{name = "Your Name", email = "you@example.com"}
]
license = "MIT"
license-files = ["LICENSE"]
classifiers = [
"License :: OSI Approved :: MIT License" # これが無いとPyPIでライセンスが表示されない
]
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"scipy (>=1.16.3,<2.0.0)"
]
[project.urls]
homepage = "http://example.org/home"
repository = "http://example.org/repo"
[tool.poetry]
packages = [{include = "project", from = "src"}]
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
[dependency-groups]
dev = [
"pytest (>=9.0.2,<10.0.0)"
]
PEP 621対応前の書式として tool.poetry セクションに書く方法も使用可能ですが現在は deprecated です。
[tool.poetry]
description = "短い説明文"
license = "MIT"
homepage = "http://example.org/home"
repository = "http://example.org/repo"
readme = "README.md"
まとめ
PoetryはPipenvに無かったパッケージ公開機能も含んだより統合されたツールです。
4.4 Rye
pipenvとpoetryがバージョン管理を対象としなかったのに対してryeがすべてを管理することができるツールとして現れました。
パッケージビルド・公開も備えています。
ビルドは内部的にHatchを使っています。
$ rye build # ビルド
$ rye publish # PyPIへのアップロード
pyproject.toml は Poetryと同様です。
[project]
name = "project-rye-test"
version = "0.2.0"
description = "Add your description here"
license = "MIT"
classifiers = [
"License :: OSI Approved :: MIT License"
]
dependencies = [
"scipy>=1.16.3",
]
readme = "README.md"
requires-python = ">= 3.8"
[project.urls]
homepage = "http://example.org/home"
repository = "http://example.org/repo"
[build-system]
requires = ["hatchling==1.26.3"]
build-backend = "hatchling.build"
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=9.0.2",
]
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["src/project"]
2025年12月16日現在、https://github.com/astral-sh/rye/issues/1446#issuecomment-2546425240 で報告されているように、hatchling のバージョンを指定しないとアップロードが失敗します。
まとめ
オールインワンツールとしてパッケージビルド・公開も含んでいます。
不具合に遭遇しましたがすでに非推奨なのでuvに移行するべきです。
4.5 uv
はじめはパッケージの依存解決が高速な仮想環境管理ツールでした。
やがてPythonプロジェクト管理ツールとして機能が追加されRyeと同様にオールインワンツールとなり、Ryeの後継プロジェクトに位置しています。
ビルド
Part 2: 🐍 Pythonバージョン管理 > 2.5 uv では uv init にオプションを付けませんでした。 その場合pyproject.tomlに build-system のセクションがありません。
https://docs.astral.sh/uv/concepts/projects/init/#libraries
PyPIにアップロードするライブラリを作る場合はinitに—libオプションを加えます。
$ uv init project2 --lib
libを付けなかったprojectではmain.pyがエントリポイントとして存在しますが、“—lib”を付けた方は src/プロジェクト名/__init__.py が作られます。
前者はフラットレイアウト、後者はsrcレイアウトと呼ばれます。
https://packaging.python.org/ja/latest/discussions/src-layout-vs-flat-layout/
pyproject.toml
[project]
name = "project2"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
[build-system]
requires = ["uv_build>=0.9.17,<0.10.0"]
build-backend = "uv_build"
ビルドシステムはuv独自のものがあります。
ビルド・配布実行例
ubuntu@x:~/project2$ uv build
Building source distribution (uv build backend)...
Building wheel from source distribution (uv build backend)...
Successfully built dist/project2-0.1.0.tar.gz
Successfully built dist/project2-0.1.0-py3-none-any.whl
ubuntu@x:~/project2$ uv publish
まとめ
コマンド自体は単純ですね。
pyproject.tomlにbuild-systemがあるかどうかで挙動が変わります。
4.6 Anaconda
PyPIとは別の独自エコシステムで、meta.yamlでパッケージを定義し.tar.bz2形式でビルドします。Anaconda Cloudに公開し、ユーザーはチャンネルを指定してインストールします。
PyPIとの互換性はありません。
4.7 まとめ
設定ファイルはsetup.py/setup.cfgからpyproject.tomlへと標準化されました。
ビルドと配布はsetuptools+twineを使っていたのが、管理ツールがコマンドを備えるようになりました。
Part 5: ⚙️ タスクランナー
開発中には、lint、format、初期化スクリプトなど、繰り返し実行するコマンドが多数あります。 これらを毎回手打ちするのは非効率なため、タスクランナーでまとめて管理したくなります。
NodeJSだとpackage.jsonのscriptsに書いてnpm runで呼び出しているやつです。
このPartでは、Pythonプロジェクトで使われるタスクランナーを比較します。
5.1 比較
| ツール | 設定ファイル | 依存関係管理 | 並列実行 | 特徴 |
|---|---|---|---|---|
| make | Makefile | ✅(宣言的) | ✅ | UNIX標準・ファイルベース |
| Pipenv | Pipfile | ❌ | ❌ | 環境統合 |
| Rye | pyproject.toml | ▲ (chain) | ❌ | 統合ツール |
| Poe the Poet | pyproject.toml | ✅ | ✅ | 共存指向 |
| invoke | tasks.py | ✅(pre/post指定) | ❌ | Pythonコード |
| mise | mise.toml / mise-tasksディレクトリ | ❌ | ❌ |
makeはどこにでもある汎用的で強力なツールです。
Pipenv, Rye, miseはツールに備え付けのタスクランナーです。手っ取り早く使えます。
Poeは環境管理ツールとは独立した、高機能なツールです。
invokeはPythonコードでタスクを定義します。
ここにきてuvにはタスクランナーがありません。Issueで議論はあるようです。 https://github.com/astral-sh/uv/issues/5903
5.2 make
makeはビルド自動化ツールです。
Makefileに依存関係を書いてファイルのタイムスタンプに基づいて実行をします。
ファイルに基づかない任意のコマンドも定義できます。
Part 1でもpythonをソースからビルドするのに使いました。
makeは1976年から存在する歴史のあるビルド自動化ツールです。
Linuxなら簡単にインストールできます。
これはPython開発でMakefileでスクリプトを実行する例です。
.PHONY: lint format clean build
lint:
ruff check src/
format:
black src/
clean:
rm -rf dist/ build/ *.egg-info
find . -type d -name __pycache__ -exec rm -rf {} +
build:
python -m build
all: format lint build
$ make lint
ruff check src/
$ make all
black src/
ruff check src/
python -m build
makeの特徴は宣言的に依存関係を定義できて依存が衝突しないものは並列で実行できることです。
例
.PHONY: lint format build
lint:
ruff check src/
format:
black src/
build: format lint
python -m build
make buildを実行すると:
- buildがformatとlintに依存
- 自動的に format → lint → build の順に実行
実行順序はmakeが自動で解決します。
依存関係のないタスクは自動的に並列実行されます。
$ make -j4 # 4並列で実行の例
この場合、formatとlintが並列で実行され、両方が完了してからbuildが実行されます。
まとめ
Linuxならば簡単に導入できます。
宣言的な依存関係定義があります。
並列実行できます。
汎用的です。
始祖にして至高のツールです。
Makefileがシェルスクリプトに似ながら癖が強いことは気にしないでおきましょう。
5.3 Pipenv
https://pipenv-ja.readthedocs.io/ja/translate-ja/
PipenvはPipfile の scripts でタスクを定義できます。
定義例
[scripts]
lint = "ruff check src/"
format = "black src/"
build = "python -m build"
実行例
$ pipenv run lint
$ pipenv run format
5.4 Rye
オールインワンツールにふさわしくタスクランナーも入っています。
pyproject.tomlを使いますが、あくまでツール拡張の機能なのでセクションは tool.rye.scripts です。
pyproject.toml
[tool.rye.scripts]
devserver = "flask run --app ./hello.py --debug"
devserver_env = { cmd = "flask run --debug", env = { FLASK_APP = "./hello.py" } }
rye run で実行します。
$ rye run devserver
$ rye run devserver_env
chain
複数のタスクを一緒に実行するために chain があります。
https://rye.astral.sh/guide/pyproject/#chain
[tool.rye.scripts]
lint = { chain = ["lint:black", "lint:flake8" ] }
"lint:black" = "black --check src"
"lint:flake8" = "flake8 src"
こういったタスクランナーではシェルとして&&で繋げて対処する場合もありますがRyeでは不要です。
lint = "tool lint:black && tool lint:flake8"
5.5 poethepoet
Poe - poethepoet
https://github.com/nat-n/poethepoet
独立したタスクランナーです。
A batteries included task runner that works well with poetry or uv.
READMEにあるように、Poetryやuvにはタスクランナーが無いのでPoeを併用する使い方があります。
pyproject.toml を使います。
GitHub Poeリポジトリより
定義例
pyproject.toml
[tool.poe.tasks]
test = "pytest --cov=my_app" # a simple command task
serve.script = "my_app.service:run(debug=True)" # python script based task
tunnel.shell = "ssh -N -L 0.0.0.0:8080:$PROD:8080 $PROD &" # (posix) shell based task
実行例
$ poe test -v tests/unit # extra CLI arguments are appended to the underlying command
Poe => pytest --cov=my_app
5.6 invoke
invokeは、Pythonコードでタスクを記述するタスクランナーです。
Pythonで開発している、そこにPythonがある。なので周辺ツールもPythonで動くようにする。というのも当然の発想です。
詳しいことはマニュアルに移譲します。 https://www.pyinvoke.org
引数preとpostで前後に実行するタスクを指定できます。これはうれしい。
複雑なことをしようとするとき例えばMakefileだと別途シェルスクリプトやPythonスクリプトに切り出したりします。
invokeはPythonコードなので、複雑なロジックもそのまま記述できます。
それをPythonで書くのが果たして楽なのかは、場合によります。
5.7 mise
こちらはマニュアルに移譲します。 https://mise.jdx.dev/tasks/
5.8 まとめ
選択方法は
Pipenv, miseなどそれ自身にタスクランナーがあればそれを使う。
Poetry, uvなどタスクランナーが無い場合はpoeを組み合わせる。
といったところでしょうか。必ずこれを使えというのは無いので自由です。
あるいは、汎用的なmakeがいいでしょう。makeはとてもエレガントなのであらゆるツールがmakeに代わろうとしても結局makeに戻ってくるんですよね。
Part 6: 補足
これまでのPartに収まらなかったトピックを書き連ねています。
6.1 PDM
https://github.com/pdm-project/pdm
PDMも多機能なツールです。
PEP 582 https://peps.python.org/pep-0582/
venvのような仮想環境ではなくNodeJSのnode_modulesのような__pypackages__ディレクトリを使ってライブラリを管理する提案がありました。
最終的にRejectされましたが、これに準拠していたPython管理ツールがPDMです。
https://frostming.com/en/2022/pdm-2/
しかし、PEP 582 Acceptの見込みがないことからVersion 2.0でvirtualenv方式をデフォルトとしました。
変わった歴史があるツールです。
6.2 ツールの系譜
PEP仕様とツール実装の試行錯誤の歴史です。
分散したツール群
Pythonプロジェクトには多数のツールが必要です。
┌─────────────────┐
│ pyenv │ ← Pythonバージョン管理
├─────────────────┤
│ venv/virtualenv │ ← 仮想環境
├─────────────────┤
│ pip │ ← パッケージインストール
│ pip-tools │ ← 依存関係解決・ロック
├─────────────────┤
│ setuptools │ ← パッケージング
│ twine │ ← PyPI公開
├─────────────────┤
│ make/invoke │ ← タスクランナー
└─────────────────┘
設定ファイルも複数あります。
setup.py,setup.cfg: パッケージングrequirements.txt,requirements-dev.txt: 依存関係MANIFEST.in: パッケージに含めるファイル
これに加えてタスクランナーやlinter/formatterなどの周辺ツールの設定ファイルもあります。
ツールが個別にあるのはそれぞれの役割を果たすCLIということでUNIX哲学にもある形で何も悪いことではありません。
しかし、一つのツールで全部やってくれて、これさえ入れればOKなものを求めるのも人の心です。
系譜
ツールが互いの改善を取り込んだり直接使用していたりするので正確ではないですがあえて一本道にするならばこうなります。
分散したツール群
⇂
Pipenv (2017): 仮想環境・パッケージ管理・依存管理を統合した設定ファイルで行うツールの登場
↓
Poetry (2018): pyproject.toml 準拠、パッケージビルド・配布機能統合、依存関係解決速度改善と厳格化
↓
PDM 0.0.1 (2020): PEP582準拠のパッケージインストール機構を持つツールとして登場
⇂
⇂ (pip 20.3 (2020) にて依存関係解決改善・厳格化)
⇂
PDM 2.0.0 (2022): PEP582のAcceptの見込み無しとしてvirtualenvをデフォルトのパッケージ管理方式に変更
⇂
Rye 0.1.0 (2023): Pythonバージョン管理も統合したオールインワンツールとして登場
↓
uv 0.1.0 (2024-02): アルゴリズムと処理の最適化で高速なパッケージインストールを行うpip代替として登場
⇂
Rye 0.34.0 (2024-05): パッケージインストールにpipに代わりuvを導入
⇂
uv 0.3.0 (2024-08): プロジェクト管理・Pythonバージョン管理機能を追加
⇂
uv 0.4.0 (2024-09): パッケージビルド・配布機能を追加
⇂
Rye 0.44.0 (2025-02): 開発終了・uvへの移行を推奨
2025年末現在の状況
- 基本的なツール群も使用可能
- Poetryは安定版として継続
- Ryeは非推奨、uvへ移行推奨
前書き それで何を使えばいいか に繋がります。
6.4 再現性とは何か
やや極論気味に「依存関係を固定しても、本当に再現できるのか」を考えてみます。
poetry.lockやuv.lockで依存関係を固定すれば同じ環境を作れるようになりました。
本当でしょうか。
ロックファイルにはこんな感じで書かれています
[[package]]
name = "requests"
version = "2.32.5"
source = { registry = "https://pypi.org/simple" }
PyPI(外部リポジトリ)への依存が残っているので、未来への保証はありません。パッケージが削除されたり、リポジトリが利用できなくなる可能性があります。
より確実にするには、パッケージ自体のコピーを持っておきます。pip downloadでパッケージをダウンロードしておいたり、組織内でプライベートPyPIミラーを運用してパッケージを保存したりします:
ダウンロード例
$ pip download -r requirements.txt -d packages/
$ pip install --no-index --find-links=packages/ -r requirements.txt
ただし、これでもPython本体やシステムライブラリの再現性は保証されません。
Pythonパッケージだけでなく、環境全体を管理する方法もあります。
Nixは、Pythonパッケージだけでなくシステムライブラリまで含めた依存グラフをハッシュで管理します。すべての依存関係を記録できますが、Nixpkgsやインストール対象も通常はインターネット由来のリソースなので自身で管理できない外部のリソースです。
Dockerなどのコンテナで環境を管理することもあります。Dockerfileを書いてビルドすれば環境を構築できます。13
FROM python:3.11-slim
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install -r requirements.txt
$ docker build -t myapp:1.0.0 .
ただし、このDockerfileから再ビルドすると、結果が変わる可能性があります。FROM python:3.11-slimは時間とともに更新されますし、apt-get install gccも最新版が入ります。
やろうと思えばバージョンを固定することもできます。
FROM python:3.11-slim@sha256:1234567890abcdef...
RUN apt-get update && apt-get install -y \
gcc=4:12.2.0-3 \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install -r requirements.txt
はい、面倒です。
そして固定したとしてPythonパッケージの例と同様に外部のリポジトリなので将来も残っている保証はありません。
例として
- DockerHubで古いイメージは消すようにしている場合があります。
- Linuxディストリビューションのパッケージリポジトリがサポート期間を終えたあとに運営のメインからアーカイブ扱いの別サーバーに移動することがあります。 (この場合は消えていないのでパッケージインストールの参照リポジトリを変えるだけでよい)
といったことがあります。
将来も動く同じものが必要なら、イメージをファイルとして保存しておくのが現実的です:
$ docker save myapp:1.0.0 > myapp-1.0.0.tar
イメージファイル(.tar)を保存すれば、外部リポジトリに依存せず環境を復元できます。
ロックファイルは外部リポジトリへの依存が残りますし、パッケージのコピーでもPython本体やシステムライブラリは固定されません。将来への確実性を高めるには、動く環境全体のファイルコピーを持っておくことです。
最後に信じられるのは複製だけです。
6.5 CI/CDとキャッシュ
依存解決の改善などでライブラリインストールが速くなった。
とはいえ、CIで毎回ダウンロードはネットワーク帯域の無駄です。 14
また、ネイティブライブラリのビルドが必要なものはさらに時間が必要です。
こういったときはキャッシュを使うことを検討します。
後はマニュアルに投げます。
uvを見ることにしましょう。
uv Concepts Caching caching-in-continuous-integration
With uv, it turns out that it’s often faster to omit pre-built wheels from the cache (and instead re-download them from the registry on each run).
なんと、ダウンロードするだけで使えるライブラリwheelの場合はキャッシュを使わない方が速いらしいです。 クライアントでのネイティブライブラリビルドがあるものは恩恵があるのでパッケージのタイプによって動作を切り替えるオプションがああります。
他にもキャッシュの設定ミスによって予期しないゴミが混ざることもあるので注意が必要です。
6.6 WindowsとPython
2025年現在Windowsで本格的にPythonを使った開発をするならuvを使うとよいでしょう。
ですが、動かすのは小さいスクリプトであるとか、pipで導入するCLIツールや、git cloneしてrequirements.txtから依存ライブラリをインストールするPython製のツールを使うなどというときは Python Foundation公式の PIM - Python Install Manager もおすすめです。
Python Install Manager - https://apps.microsoft.com/detail/9nq7512cxl7t
PIが出る前は悩みがありました。
- Windowsの公式インストーラーだとPATH設定が手間で環境が散らかる
- 旧公式ツールPythonランチャーだと個別のバージョンのインストールが手動なので手間
- Anacondaだとcondaの環境に縛られる
- サードパーティーの切り替えツールでもパス設定などで環境の管理が手間だったりする
これが解消されます。
あとがき
Part1のあと、比較に入ったところで内容が思ったより増えたのできつかったです。Partごとに記事を分ける量でした。スクロールで見づらいのはお許しください。
Anacondaをあまり深く掘れなかったのはちょっと心残りですね。PDMの存在を知らなかったので扱いが大雑把になってしまったのも良くない。それとHatchも書くべきでした。
Pythonだらけで満足したのでしばらく”Python”の文字は見ないようにします。
脚注
-
むしろ厚いツールの裏側で起きた深い場所のエラー原因追及をすることになったとしたらこの辺の知識が活きます。 ↩
-
トレードオフというやつです。そのツールが行う抽象化とユーザーへのやり方の縛りが心地よく受け取られるとき、それは良いツールといえるでしょう。逆に公開されていないインターフェースや設定を弄ってまで何かを成し遂げなければならなくなったとき、そのツールは地雷となっています。 ↩
-
挙げられていないのはこれを書くまで私が存在を知らなかったからです。 ↩
-
人類は脳に経験を含めた知識の移転が可能になるといいですね。 ↩
-
「ビルドのためにパッケージマネージャーに甘えてるじゃないか」はい、完全に本質を捉えた正しい指摘です(AI風)。そんなあなたには ゼロからミニマルなLinuxディストリビューションを作る Linux From Scratch プロジェクトをお薦めします。 ↩
-
makeがメモリ不足で落ちる場合はCPUスレッド数分の並列を行う
-j"$(nproc)"を除くか、-j2など小さい値でmakeを実行してください。 ↩ -
SNS上でこう言った議論は個々の事情が後出しになる前提条件のわからない言い合いなので空中戦になりがちです。惑わされてはいけません。 ↩
-
新しいものを導入させたいときに「今までの方法ではできない」と言う、古いツールをよく知らないが故の誤解で摩擦になったりします。認識のすり合わせのためにもよく把握しておきましょう。この進化の形はプログラミング言語やフレームワークにも当てはまります。 ↩
-
なんでもできる状態で秘伝のタレを作ったり設定職人になる楽しさもありますが、ソフトウェア開発は知的労働を集約する産業なので、各人に余計な思考のリソースを使わせないことが求められます。賃金のためには自由を捨てることもあります。 ↩
-
ツールやソフトウェアを作る人間は、自分の定義したやり方を人に押し付けて喜ぶという点において本質的に支配欲求があり、ツールを受け入れ縛りに喜んでいる人は従属欲求があると言えます。 ↩
-
pyproject.toml を使うことと、PEPで標準化されたものは各ツールが準拠を目指しますがツールごとの専用の設定は互換があるわけではないのでツール移行のときはしっかり検証しましょう。 ↩
-
この”科学計算”は時代の流行とマーケティングの都合で”機械学習”、または”AI”に言い換えられます。 ↩
-
仮想マシンや仮想マシンを構成するVagrant, ansible も同様です。 ↩
-
CIプラットフォームだと内部のネットワーク的に近い場所にミラーを置いていたりするので通信効率としてはあまり問題にならなかったりするかもしれません。セルフホストのCIランナーだと効果があると思います。 ↩