CUBE SUGAR CONTAINER

技術系のこと書きます。

Python: Unix における python* コマンドと処理系のバージョンについて (PEP394)

今回は Unix ライクなシステムにおける python* コマンドの振る舞いと、処理系のバージョンについて色々と書いてみる。

きっかけは、以下のブログ記事を目にしたため。

rheb.hatenablog.com

上記のブログでは Red Hat Enterprise Linux 8 に搭載される予定の Python と、それを扱うコマンド群について紹介されている。 そして、RHEL8 がそのような仕様に落ち着いた理由として以下の PEP (Python Enhancement Proposal) が挙げられている。

www.python.org

この PEP394 というドキュメントには、Unix ライクのシステムにおいて推奨される python* コマンドの振る舞いなどが記述されている。 そこで、今回は PEP394 に書かれている内容について紹介したい。 先のブログでは、話の切り口が「RHEL8 における仕様」なのでやむを得ないものの、やや説明が不足しており補足したい点もあった。

python* コマンドで実行される処理系のバージョンについて

まず、PEP394 には python* コマンドを実行したときに、どのバージョンの処理系が呼び出されるべきなのか書かれている。 例えば、次のようにコマンド名でバージョンを明示的に指定したときは、そのバージョンの処理系が呼ばれることになる。 もちろん「そのバージョンの処理系がインストールされていれば」という前提のもとで。

$ python2  # => Python 2.x の処理系が使われる
$ python3  # => Python 3.x の処理系が使われる

問題となるのは、バージョンが明示的に指定されていないとき。 一体、どのバージョンの処理系が呼び出されるべきなのだろうか。 その答えは「現時点では Python 2.x の処理系が使われることが推奨されている」になる。

$ python  # => 現時点では Python 2.x の処理系が使われることが推奨されている

現時点では?

太字にした通り、この挙動が推奨されているのは、あくまで現時点 (2019-01) の PEP394 ではという注釈つきになる。 なぜなら PEP394 には Future Changes to this Recommendation (この勧告に対する将来の変更) という項目があるため。

この項目には、次のような記述がある。(カッコ内は拙訳)

This recommendation will be periodically reviewed over the next few years, and updated when the core development team judges it appropriate. As a point of reference, regular maintenance releases for the Python 2.7 series will continue until at least 2020. (この勧告は将来の数年間に渡って定期的に見直されます。そして、コア開発チームが妥当と判断したときに更新されます。参考までに、Python 2.7 系の定常的なメンテナンスリリースは少なくとも 2020 年まで続きます。)

つまり、将来的にはバージョン指定なしの python コマンドで Python 3.x の処理系が使われることを推奨する内容に更新される余地がある。

例外について

ところで、上記の振る舞いは一部のディストリビューションと仮想環境では例外として扱われている。

一部のディストリビューションというのは、例えばこの PEP が勧告される以前から Python 3 移行を始めた、ある意味で優秀なコミュニティもあったりするため。

www.archlinux.org

もう一つの仮想環境というのは venvvirtualenv を使った環境を指している。 仮想環境の中では、環境を作るときに指定されたか、あるいはデフォルトの処理系が python コマンドで使われる。

$ python3 -m venv myvenv 
$ source myvenv/bin/activate
(myvenv) $ python -V
Python 3.7.2

シェバン (Shebang) について

PEP394 には、シェバン (Shebang) に関する記載もある。

シェバンにおいては、特定のバージョンの Python でしか動かないモジュールならバージョンを指定することが推奨されている。 例えば、Python 2 でしか動かないなら以下のようにする。

#!/usr/bin/env python2
...

Python 3 でしか動かないなら、こう。

#!/usr/bin/env python3
...

バージョン指定のないシェバンは、モジュールが両方のバージョンで動く場合に用いることが推奨されている。

#!/usr/bin/env python
...

インタプリタから別のインタプリタを起動する場合

また、subprocess なんかでインタプリタの中から別のインタプリタを呼ぶときは sys.executable の内容を使うのが良い。 ここには自身の処理系のパスが格納されている。

$ python3 -c "import sys; print(sys.executable)"
/usr/local/opt/python/bin/python3.7

特定のコマンド名 (python2, python3, python, etc) を使うと、誤って別の処理系を呼び出したりして思わぬバグが生じる恐れがある。

まとめ

  • 前提: PEP394 の勧告は将来的に変更される余地がある
  • 各コマンドで起動する処理系のバージョン
    • python2 # => Python 2.x
    • python3 # => Python 3.x
    • python # => 今のところ Python 2.x
  • 上記の例外
    • 一部のディストリビューション (ArchLinux など)
    • 仮想環境 (venv, virtualenv)
  • シェバン (Shebang) を書くとき
    • python2 # => Python 2.x のみで動作する
    • python3 # => Python 3.x のみで動作する
    • python # => 両方のバージョンで動作する
  • インタプリタの中から別のインタプリタを起動するとき
    • sys.executable を使う

いじょう。