トホホな疑問(26) Python, Windowsでのshebang行

JosephHalfmoon

今日は、Windows上でPython3系とPython2系、どっちのPythonが起動されるかのトホホな話です。正直、惰性で書いてましたShebang行、#!/usr/bin/python みたいな先頭行。でもね、惰性じゃイケなかった。それにまたまた PYTHONPATHが「悪さ」をしてくれるし。。。ちゃんと考えて設定しておかないとダメだ。

※「トホホな疑問」投稿順Indexはこちら

まず、最初にお断りしておくと、venvとか condaとか、「仮想な」人達(ヒトだったか)を使っていないわけじゃないのです。しかし、普段使いのマシンでは、わざわざ仮想環境で切り替える必要もなかった。ダラダラと素のPythonで十分でした。そんな難しいことやらないし。しかし、昨年末にようやくPython2系からPython3系へとスイッチしたこともあり、昨年来、Windows上では、2つのコマンドプロンプトを使い分けてきました。

    • Python3系にパスを向ける設定が自動で行われるコマンドプロンプト
    • Python2系にパスを向ける設定が自動で行われるコマンドプロンプト

なお、PowerShellはPython3系のみといたしました。さてそこで、

$ python xx.py

みたいにスクリプトを動かしていたのは幸せでした。ちゃんと3系設定では、pythonと打てば python3系が立ち上がり、2系設定ではpython2系です。これは当然設定しわけているPATHのお陰であります。これだけだったら、何の不自由かあらん(ある筈ない。)しかし、他にも起動方法あったよな、バッチファイルの中でpython, python何度書いているのもメンドイし。。。

    • py コマンドを使う
    • .py 拡張子への関連付けを使う

pyコマンドは、py -2 yy.py とすれば、Python2系を立ち上げて処理してくれ、py -3 zz.py とすれば、Python3系で処理してくれる筈。

Python3系にパスを向けてあるコマンドプロンプトの中で

$ py

と引数を与えずに起動したところちゃんとPython3系が立ち上がります。当然

$ py xx.py

などとすれば、Python3系によって処理されるに違いない、と思いきやエラーです。間違いなどある筈のない標準モジュールの奥底からエラーがやってきます。どうして?

$ python xx.py

とやると、ちゃんと正常に処理されるのに!当然、PATHもPYTHONPATHも同じものが見える筈。。。

ふと思い立って、拡張子で関連ずけされている起動方法をやってみました

$ xx.py

という感じ。エラー。先ほどと同じエラー。

お気づきでしょうか、この2つ症状は同じですが原因は違います。pyコマンドでの起動がうまく行かなかったのこそ、

Shebang行

のためのなのでありました。

#!/usr/bin/python

などと書いても、だいたいWindowsには /usr/bin など普通は無いし、シェルだってShebang行など解釈してくれないし。意味ないんじゃないかなどと心の底で思っていた私です。しかし、そうです、pyコマンドは、引数のShebang行をちゃんと読み取って解釈してくれるのでした。

#!/usr/bin/python

と書くと、python2系が起動されます。

#!/usr/bin/python3

と書くと、python3系が起動されます。その辺の詳しい説明のあるご本家マニュアルはこちら

 

これに対して拡張子による関連付けでの呼び出しが不成功だったのは、2つの原因が重なっていました。

    1. 拡張子の関連付け(Windows OSの機能)は以前のPython2系のexeに設定してあったのを忘れていた
    2. 実行環境はPython3系用のPATHとPYTHONPATHが設定されていた

つまり、関連付けで起動されるのはWindowsが覚えていたPython2系のexeで、これにxx.pyが渡されるのです。xx.pyそのものはPython2系でも実行可能なコードだったのですが、あろうことか、

PYTHONPATHにPython3のLibへのパスが含まれていた

結果、Python2の実行ファイルは、PYTHONPATHから得たPython3用のライブラリを読んでしまい、エラーとなっていました。とほほ。

この教訓としては、「PYTHONPATHにはご丁寧に標準ライブラリへのPATHなど書かない」ってことでしょうか。どうせ、Pythonインタプリタが立ち上がった時点で、(sys.path見ていると)標準ライブラリへのパスは内部で設定されるようであります。自分で書いたモジュールなどへのPATHなどのみ書いておけば、関連づけされているPythonでちゃんと実行されます。

cmd.exe上で、assocとかftypeとかで関連ずけを確認し、変更(管理者権限いると思います)できます。今回、関連付けはPython3に変更しました。

そして、

Windows上でもShebang行は起動したいバージョンに向けてちゃんと書く

さすれば、コマンドプロンプトを2種用意するような原始的なことをせずとも、pyコマンドが、起動したいバージョンをちゃんと見分けてくれる、と。こんなことも気付いておらなんだ。。。トホホ。

トホホな疑問(25) Python, argparse, help?? へ戻る

トホホな疑問(27) M5StickC、Uartを使う へ進む