Pythonで作ったCLIツールは
PyPI
を通して配布することが出来ますが
必要なPythonのバージョンがあったり、依存パッケージを色々インストールしないといけないとなると
pipでグローバルな環境に入れるのもちょっと微妙。
仮想環境を作ってそこで管理すれば他のライブラリ等を気にせず使えますが、 Homebrewを使うとその辺が簡単に出来ます。
HomebrewでのPythonツール用のFormulaの作成
以下にPythonのFormulaに関するドキュメントがあります。
ここだと色々と思想的なものが書かれているのとちょっと古い?方法が書かれていますが、
以下ではPyPIで配布されているパッケージのFormulaを作る際に実際にやりやすい手順を紹介。
brew create
まず、テンプレートを作るため、brew createコマンドを使います。
ただ、これ今ちょっと使いづらくなっています。 デフォルトではHomebrew-coreのTapの中に作る設定になっていますが 最近API経由のインストールがHomebrewのデフォルトになっているので そのTapが存在しないため
1
| |
といったエラーが出てしまいます。
なので適当なTapを用意して上げる必要があります。 homebrew-core を入れるでも良いのですが重いので適当な別のものを入れたほうが楽です。
もし適当なものがなければhomebrew-testtapという名前の空レポジトリをGitHubに作って
1
| |
とかで入れればOK 1。
rcmdnk/homebrew-testtap が空Tapなので、これを使っても良いです。
ローカルなtapを持ったらbrew createを実行します。
1
| |
brew createは--python, --ruby, --goなど各言語の独自環境やビルド用の
templateを作るためのオプションが用意されているのでこれを使います。
python用FormulaではURLにはPyPIでのSourceの圧縮ファイルを指定します。
以下では cocoro というCLIツールで作ってみます。
PyPIのcocoroのファイルをダウンロード のページに有る最新のtar.gzのファイルのURLを取得。
これを使って以下のようなコマンドを実行。
--set-nameオプションはつけない場合はデフォルトの値がcocoro-0.1.4とバージョンの付いた名前になって、
これを変更するかどうか聞かれるプロンプトが出ます。
バージョンは外さないと行けないので最初から--set-nameで指定しています。
--set-licenseでのライセンス指定などは後からエディタで変更してもOK。
1
| |
これで以下のようなファイルができ、それをエディタで開いた状態になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
ファイルはtapの中の/opt/homebrew/Library/Taps/rcmdnk/homebrew-testtap/cocoro.rb (環境によって違う、$(brew --repo rcmdnk/testtap)/cocoro.rb)にあります。
このファイルは$ brew edit cocoroとすることでもエディタで開くことが出来ます。
URLで指定したものがurlに入り、そのsha256の値は自動的に取得されています。
依存するHomebrewのパッケージとしてはpythonがあります。
もし(Homebrewで入れられる)特定のPythonのバージョンを使いたい場合は
[email protected]などに変更します。
Homebrew-coreに入れる場合など、testをきちんと定義したい場合はpythonというエイリアスだと
1 2 | |
といったエラーになってしまうので[email protected]などきちんとバージョン含めたパッケージ名にする必要があります。
pyproject.tomlやsetup.pyに書かれた依存関係のあるパッケージに関してはすべて
resourceとして追加されています。
きちんと定義されたパッケージであればもうこれでOKで、後は
descに適当な紹介文を、homepageにPyPIのパッケージのページかGitHubのページ、
もしくはちゃんとしたHomepageがあればそれを記入しておけばとりあえず完成です。
もし依存関係の記述が不十分で他に必要なパッケージがある場合には
自分でそのパッケージのURLとハッシュ値を調べてresourceに追加する必要があります。
Formulaが出来たら
1
| |
としてインストールできます。
インストールされたもの
1 2 | |
こんな感じでコマンドがHomebrewのbinディレクトリにインストールされています(これ自体はシンボリックリンク)。
(opt~の部分は環境によって違う、$(brew --prefix)/bin/cocoro)
中身は
1 2 3 4 5 6 7 8 | |
となっていて、これは通常通りpip installで入れた場合と内容は基本的に同じです。
ただ、Shebangを見てみると
1
| |
となっていて、このpythonは /opt/homebrew/Cellar/cocoro/0.1.4/libexec/に作られたPythonの仮想環境のものになっています。
この仮想環境を直接使うことは通常はないかと思いますが、
1
| |
で入ることも出来ます。
こんな感じで各Fomrula毎に仮想環境を用意してその中に必要なパッケージを入れて実行しているので 他のPython環境と競合せずに管理できます。
ちょっと注意が必要なのはHomebrewでインストールしたPythonのpipコマンドを使って同じツールをインストールすると
同じく/opt/homebrew/bin/cocoroとしてインストールされるので
競合してしまいます。
後からbrewで入れると
1
| |
みたいに出てbinへの実行ファイルのリンクが作れません。
仮想環境やリンク元のファイルは出来ているので、pip uninstall cocoroとしてからbrew link cocoroするか
brew link --overwrite cocoroで矯正上書きしてしまうかで置き直せます。
インストール時間
上のcocoroはそれほど依存パッケージを持っていませんが、
それでもbrew installで入れると普通にpip installするよりも結構時間がかかりました。
pipなら1,2秒のところ(空の仮想環境に入れてみるテスト)、
brew installだと5分位かかりました。
1
| |
の部分がやけに時間かかったみたいで、--no-binaryでビルドするようになってるのでパッケージによっては時間がかかるものが出てきます。
他のものはそこまで時間はかかってないので殆どの場合ではbrewでも数秒から数十秒程度で終わると思います。
(仮想環境作ったりパッケージビルドしたりするので多少は時間がかかる。)
単純に仮想環境でpip install <package>==<version>で依存関係も含めて全部入れてくれるような
オプションもあっても良いな、とは思います。
それだとインストールが速いのと、Formulaもurlの代わりにcocoroなどを指定するpackage、
それとバージョン指定のversionを書くだけでシンプルになってresorceも要らなく出来ます。
ただ、Python for Formula Authors — Homebrew Documentation を見るとそういうのは思想に反する感じではありますが。
パッケージのアップデート
上にあるように各パッケージはすべてバージョン指定された形でそのソースファイルのURLとハッシュが指定されていますが、 これを手でアップデートするのはかなり大変です。
そんなときのためのコマンドがbrew update-python-resources。
これ使うにあたって
pipgripというツールが必要なのでこれを別途
1
| |
としてインストールしておく必要があります。
これで
1
| |
とすると各パッケージのバージョンの再確認を行ってくれます。
このツールを使うに、
これはHomebrewのTapの中にないものでも直接適用することが出来て、 カレントディレクトリにcocoro.rbがあれば
1
| |
とすればそのファイルをアップデートしてくれます。
これを使えば、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
みたいな感じの最小限のformulaを書いてbrew update-python-resourcesを適用することでもFormulaを完成させられます。
もとの cocoro-0.1.4.tar.gzのハッシュ値は自分で求めないといけませんが、個人的には 以下のようなスクリプトを使ってURL先のハッシュ値を取得できるようにしています。
配布
出来たら
$(brew --repo rcmdnk/testtap)/cocoro.rb
をコピーして、配布用のhomebrew-mypackagesみたいなtapレポジトリに追加してGitHubに上げれば
1
| |
でインストールできるようになります。
まとめ
pipだけで配布できるものをわざわざHomebrewを使って、
ということで配布側にはちょっと手間がかかりますが、
ユーザー側としてはHomebrewさえ使っていれば
既存のPython環境を汚さずに、また、Pythonのバージョンの指定も含めて
インストールするように出来るのは結構便利ではないかな、と。
特にアップデートがあった際にpipだと直接そのパッケージをアップデートするコマンドを打たないといけませんが、
Homebrewであれば定期的にbrew update && brew upgradeとかしておけば
他のパッケージ含めてアップデートしてくれるので楽です。
また、PyPIに公開されているPythonのコマンドラインツールであればどれでも同じことが出来るので、 自分のパッケージでなくても自分の管理用にFormulaを作ってHomebrewで管理できるようにする、という手段もありかと思います。
-
warning: You appear to have cloned an empty repository.という注意が出ますがbrew createでファイルを追加テストする分には 問題なく動きます。 ↩
