Rust製パッケージをインストールしてコマンドラインから実行できるのは、なぜ?
Rust製パッケージをインストールしてコマンドラインから実行できるのは、なぜ?
- Event:
Python Meetup Fukuoka #4
- Presented:
2025/09/12 nikkie
このLTは、以下ができる理由を自分の言葉で説明するものです
$ python -m venv .venv --upgrade-deps
$ source .venv/bin/activate
(.venv) $ python -m pip install ruff
(.venv) $ ruff check --fix --extend-select I
本LTのスコープ(パッケージの場合分け)
Python製パッケージの場合(例:sampleproject)
Rust製パッケージの場合(例:Ruff)
Python 製パッケージをインストールしてコマンドラインから実行できるのは、なぜ?
$ python -m venv .venv --upgrade-deps # Python 3.13.0
$ source .venv/bin/activate
(.venv) $ python -m pip install sampleproject
(.venv) $ .venv/bin/sample # /usr/bin/sample と区別
Call your main application code here
metadata の project.scripts
[project.scripts]
sample = "sample:main"
仮想環境下にスクリプト
$ ls -l .venv/bin/sample
-rwxr-xr-x 1 user group 211 Sep 12 11:23 .venv/bin/sample
$ file .venv/bin/sample
.venv/bin/sample: a /.../.venv/bin/python script text executable, ASCII text
$ # .venv/bin は仮想環境の有効化で PATH に入っている
「エントリポイントスクリプト」(『ハイパーモダンPython』2章)
エントリポイントスクリプトの中身
#!/.../.venv/bin/python
import sys
from sample import main
if __name__ == '__main__':
if sys.argv[0].endswith('.exe'):
sys.argv[0] = sys.argv[0][:-4]
sys.exit(main())
distlib によるらしい (pip 24.3.1 実装)
シバンにPythonのパス
#!/.../.venv/bin/python
仮想環境のPython処理系が実行
import sys
from sample import main
if __name__ == '__main__':
if sys.argv[0].endswith('.exe'):
sys.argv[0] = sys.argv[0][:-4]
sys.exit(main())
🥟Python製パッケージをインストールしてコマンドラインから実行できるのは、なぜ?
インストールでテキストファイル(Pythonスクリプト)が置かれる
シバンにより、Python処理系で実行される
Rust 製パッケージをインストールしてコマンドラインから実行できるのは、なぜ?
$ python -m venv .venv --upgrade-deps
$ source .venv/bin/activate
(.venv) $ python -m pip install ruff
(.venv) $ ruff check --fix --extend-select I
仮想環境下に バイナリ
$ ls -lh .venv/bin/ruff
-rwxr-xr-x 1 user group 30M Sep 12 11:30 .venv/bin/ruff
$ file .venv/bin/ruff
.venv/bin/ruff: Mach-O 64-bit executable arm64
🔑maturin
Rustバイナリ はもちろん、pyo3などバインディングを使ったクレートをPythonパッケージとしてビルド・公開できるツール
Rust版 sampleproject を今回自作
src/main.rs
fn main() {
println!("Call your main application code here");
}
$ cargo run --quiet
Call your main application code here
pyproject.toml
追加
完全版 pyproject.toml
[build-system]
requires = ["maturin>=1.8,<2.0"]
build-backend = "maturin"
[tool.maturin]
bindings = "bin"
strip = true
ローカルでインストールして実行
(.venv) $ uvx maturin build
(.venv) $ python -m pip install target/wheels/sampleproject_rs-0.0.2-py3-none-macosx_11_0_arm64.whl
(.venv) $ .venv/bin/sample
Call your main application code here
別案:maturin develop
なら .venv/bin/sample のインストールまで
PyPIにも公開
https://pypi.org/project/sampleproject-rs/
GitHub Codespaces にて
$ pipx run --spec sampleproject-rs sample
Call your main application code here
macOS向けなどのバイナリは今後対応予定
bindings = "bin" (pyproject.toml
)
Maturin also supports distributing binary applications written in Rust as Python packages using the
bin
bindings.
Ruffの pyproject.toml
[tool.maturin]
bindings = "bin"
manifest-path = "crates/ruff/Cargo.toml"
module-name = "ruff"
python-source = "python"
strip = true
exclude = [
"crates/ruff_linter/resources/test/fixtures/**/*",
"crates/ruff_linter/src/rules/*/snapshots/**/*"
]
https://github.com/astral-sh/ruff/blob/0.13.0/pyproject.toml#L46-L55
🌯Rust製パッケージをインストールしてコマンドラインから実行できるのは、なぜ?
テキストファイルではなく、バイナリが置かれる
ビルドバックエンドに maturin を使うと、Rustで作ったバイナリがPythonパッケージになる
お前、誰だったのよ?
nikkie(にっきー)・ 1000日 ブログ を書きました!(更新中)
機械学習エンジニア・LLM・自然言語処理(We're hiring!)
