Cmderで.pyを起動してPythonバージョンを確認

/

bashなどでスクリプトを実行するときには1行目に#!でこのスクリプトを実行すべきコマンドを書いておいたりする。その際、複数のバージョンのPythonが入ってる環境だと単に./hoge.pyというコマンドでPythonを起動するとどのバージョンが起動されたかわからない。という訳でまずは以下。

import sys
print(sys.version)

これで起動されているPythonのバージョンがわかります。そんなにいうことはない。

出力例はこんな感じ。

λ version.py
3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)]

Cmderでは1行目が認識される

ここから本題。Cmderというコンソールエミュレータではbashライクに./something.pyというコマンドで、もしくは./無しでもインタプリタが起動できる。(いまどきPythonのことをインタプリタといっている人どのくらいいるんだろうか。)さらに1行目の#!アノテーションも正しく認識してくれる。無ければ勝手に.pyに反応してPythonを起動する模様。

バージョンの切り替えテスト

同じく以下のファイルがversion.pyという名前で保存されているとします。今度は#!があります。

#!python
import sys
print(sys.version)

これに対してCmderでcmd.exeをホストしている際の挙動がこちら。

λ version.py
3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)]

pythonに対してPATHは通っていますがcmd.exeだけの場合は少なくともpython version.pyが必要でした。cmd.exeだけではこんな機能は無いはずなんですけど勝手にpython3.8.0が起動されています。これはおそらくCmderの機能です。もういちど言っておくと#!pythonを書かなくても.pyに反応して勝手にPythonが起動します。

PowerShellならともかくcmdのアップデートはもうないはずなので実はcmd単体の機能で出来てたってことは無いでしょう。 というわけで特定のコードだけは3.7.x系で動かしたい場合、次のようなことが可能です。

#!python3.7
import sys
print(sys.version)

これに対する出力例はこちら。

λ python3.7 --version
'python3.7' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

λ version.py
3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)]

python3.7というコマンドにはPATHが通っていないのにちゃんと3.7.x系が起動されました。不思議ですねぇ。試しに無いコマンド、例えば#!pythenというパイセンコマンドで起動しようとして見る、などするとだいたい何をしているかどうかがわかってきます。おそらくですけど有名なスクリプトの拡張子が来たらそのままcmdには渡さずCmderのホスト側でプロセスを生成しようと試みるようです。その際、きちんとバージョン部分もパースされてます。なのでこういう切り替えが可能なんですねぇ。

適当に試した結果がこちら

λ version.py                                                                             
Unable to create process using 'pythen "C:\Users\TM23\Documents\Python\lab4\version.py" '

λ version.py
Requested Python version (2) is not installed

λ version.py
Requested Python version (0) is not installed

λ version.py
Requested Python version (4) is not installed

λ version.py
Requested Python version (3.6) is not installed

3.6.x系は消してるんでね。

結論

Cmder便利。