Python asdf + poetryからryeへの移行記録
今までasdf Python pluginでPythonインタプリタをインストールし、プロジェクトはpoetryを使って管理していた。
新しくryeというツールが出たのでこれに移行する方法を考えたい。
とりあえず、ドキュメント通りにmacOSにryeをインストールし、パスを通す。
curl -sSf https://rye-up.com/get | bash
fishを使っているので、パスはconfig.fish
にこんな感じになっている。
fish_add_path $HOME/.rye/shims
# source asdf
source $HOMEBREW_PREFIX/opt/asdf/libexec/asdf.fish
この状態で、ryeでプロジェクトを作ってPythonプロジェクトを作ってみる。
rye init rye_example
cd rye_example
rye pin 3.11
rye sync
この状態でPythonからはrye_example
ライブラリが見える見えるようになる。
rye run python
>>> import rye_example
>>>
さて、問題はここから。
Correctly installed, rye will automatically pick up the right Python without manually activating the virtualenv. That is enabled by having ~/.rye/shims at higher priority in your PATH. If you operate outside of a rye managed project, the regular Python is picked up automatically.
とあるので、rye run
を省略してもvirtual env内のPythonインタプリタが指定されていてほしいがなっていない。
$ rye run python
Python 3.11.3 (main, May 7 2023, 17:43:38) [Clang 16.0.3 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
$ python
Python 3.8.15 (default, Jun 2 2023, 15:25:38)
[Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
現状のpython
コマンドはryeのものではなく、asdfのものを指してしまっている。
$ which python
/Users/hiroya/.asdf/shims/python
これは PATH
の優先順位が良くない。
$ printenv PATH
/Users/hiroya/.asdf/shims:/opt/homebrew/opt/asdf/libexec/bin:/Users/hiroya/.rye/shims
config.fish
でasdfより後でfish_add_pathしてみる。
# source asdf
source $HOMEBREW_PREFIX/opt/asdf/libexec/asdf.fish
fish_add_path $HOME/.rye/shims
が、優先順位が変わらない...?
$ printenv PATH
/Users/hiroya/.asdf/shims:/opt/homebrew/opt/asdf/libexec/bin:/Users/hiroya/.rye/shims
config.fish
で読み込んでいるasdf用のfish script、この中身でPATHを追加しているが
cat $HOMEBREW_PREFIX/opt/asdf/libexec/asdf.fish
if type -q fish_add_path
if test -n "$ASDF_DATA_DIR"
fish_add_path --global --move "$ASDF_DATA_DIR/shims" "$ASDF_DIR/bin"
else
fish_add_path --global --move "$HOME/.asdf/shims" "$ASDF_DIR/bin"
end
...
うーん、この--move
によって先頭になっているのが問題な気がする。fishのドキュメントにもあるように、
If --move is used, it may of course lead to the path swapping order, so you should be careful doing that in config.fish.
あまり積極的に使うのはよろしくないのを理解しつつ、ryeも--move
をつけることにする。
# source asdf
source $HOMEBREW_PREFIX/opt/asdf/libexec/asdf.fish
fish_add_path --move $HOME/.rye/shims
$ printenv PATH
/Users/hiroya/.rye/shims:/Users/hiroya/.asdf/shims:/opt/homebrew/opt/asdf/libexec/bin
並びはいい感じになった。
これで python
は
$which python
/Users/hiroya/.rye/shims/python
になった。よし。これで、ryeで作ったPythonプロジェクト内だと
$ cd rye_example
$ python -V
Python 3.11.3
のように、virtualenv内のPythonを指してくれる。Pythonプロジェクト外だと
$ cd
$ python -V
Python 3.10.11
のように、グローバルに見えるPythonインタプリタを指してくれる。こっちのPythonはasdf Pythonプラグインで管理しているPythonで、
asdf global python 3.10.11
としているのでこのPythonが見えるようになっている。
今まで、pyenvやasdfを使ったグローバルとローカルのPythonの切り替えは、ローカルに.tool-versions
や.python-version
などのファイルを置き、それを参照することで切り替える事ができていた。しかし、Pythonインタプリタのバージョン自体を切り替える事はできても、ローカルにある仮想環境のパスを参照することはできなかった。
一方、pdmは、PEP582を使って仮想環境を作らずに、環境を切り替える方法というのが模索されていた。これは、__pypackages__
という特殊なディレクトリにライブラリをインストールし、Pythonインタプリタではそのパスを動的に追加してやるというもの(だと理解している)。ただ、このライブラリへのパスを追加するのはpdmがやっていたので、VSCodeなどエディタ側で利用するPythonインタプリタを指定してPythonを切り替えるという方法が使えなかった。
ryeはこれを解決するツールと言えそう。ryeで管理しておけば、コマンドは同じpython
だけど、以下のようなシームレスなPython環境が切り替えができるのはちょっと感動する。
$ cd rye_example
$ python
>>> import numpy as np # Pythonプロジェクト内ではnumpyライブラリをimportできる
>>> ^D
$ cd
$ python
>>> import numpy as np # Pythonプロジェクト外ではnumpyは入っていないPython環境になる(== プロジェクトが隔離されている)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'numpy'
これ書いていて知ったけど、pdmで使っているPEP582は取り込まない方針になっていたのか。
Virtualenv and PEP 582#
PDM offers experimental support for PEP 582 as an opt-in feature, in addition to virtualenv management. Although the Python Steering Council has rejected PEP 582, you can still test it out using PDM.To learn more about the two modes, refer to the relevant chapters on Working with virtualenv and Working with PEP 582.
ryeはあくまでもPythonプロジェクト内のPythonだけ管理してくれるので、グローバルで使うようなPythonはryeとは別でインストールしてやる必要がありそう。
グローバルで使うPythonはバージョンを切り替えることはあまりしないとは思うが、これは従来通りpyenvやasdfなどでPythonをインストールしておけば良いと思う。
ややこしいが、ryeで作ったPythonプロジェクト内で使うPythonインタプリタはryeがインストールしたPythonを使うので、pyenvやasdfでインストールしたPythonは使わないということだけ気にしておけばいいだろう。
rye install {package}
とすることでグローバルにインストールすることができます。
これにより~/.rye
にインストールされます。内容を見るとpyvenv.cfg
というファイルが作成されており、pythonのバージョン情報もあります。
なので未検証ですが、パッケージごとに違うバージョンを指定することも可能かと思います。
black
等をグローバルにインストールしてpyenv
は削除しましたが、今のところ問題なく動作しています。
コメントありがとうございます。rye install
でインストールしたツールに関しては、pyenv必要なく動作できそうですね。Pythonのバージョンとパッケージを合わせて指定が可能になりそうなのは興味深いです。
ここで疑問に思っていたのは、rye init some_project
とした時、このsome_project
内ではスタンドアロンのPythonバイナリを落としてきて使う事ができますが、このプロジェクト外ではどうなるのか、ということでした。
外部パッケージを必要とせず、全てbuiltinパッケージのみのPythonスクリプトを動かす場合、わざわざryeでプロジェクトを作る必要はないはずで、単にpython main.py
として実行したいです。ここの、
ryeで管理しておけば、コマンドは同じpythonだけど、以下のようなシームレスなPython環境が切り替えができる
のように、ryeプロジェクト外で使うためのPythonをどのように用意すれば良いのか、でした。僕の理解では、これはシステムのPython(UbuntuならaptでインストールしたPython)、もしくはpyenv、asdfなどでインストールしたPythonが必要になりそうだ、と思っています。
ryeでインストールしたpythonをグローバルで使用するには以下のコマンドを実行します。
rye config --set-bool behavior.global-python=true
ただし、rye
のversion0.9.0
で追加された機能なのでupdateの必要があるかもしれません。
rye self update
これにより~/.rye/shims
を参照したpythonを使うことができます。
> which python
/Users/myname/.rye/shims/python
別のversionのpythonを使うには以下のようにします。
> python +3.8 --version
Python 3.8.16
> python +3.9 --version
Python 3.9.16
ここまで手探りで調べましたが、直接versionを指定してグローバルにpythonをインストールする方法はわかりませんでした。
仮想環境を作成して使用したことのあるversionに関しては使えるようです。
おぉ!丁寧に調べていただいた情報をありがとうございます!
まさに欲しかった機能でした!!!asdfやpyenvと組み合わせるとなると、使い分けと構成がどうなっているのかを意識させられるのが少し辛かったのですが、これがあればもうryeだけで完結できて最高です!
asdf + poetryからryeへの移行というよりは、asdf + ryeへの移行という感じだろうか。
- asdfはグローバルのPythonのインストール
- ryeはPythonプロジェクト内で使うPythonのインストール
ただし、asdfでインストールするPythonは最初の1回だけで、追加で別のPythonのバージョンをasdfでインストールすることは無いかなぁという印象。
そういえば、ryeではblack, flake8などグローバルで使えるようにしたいツールを管理出来るそう。これを使えば、asdfでグローバルに見えるようにしているPython環境にblack, flake8をインストールする必要は無い?ということになりそう