Pythonランチャで複数のPython環境を使い分ける

2020年7月18日プログラミングPython,プログラミング

Pythonは、使用するライブラリによって対応するPythonのバージョンが異なる場合があるため、複数のバージョンのPythonをインストールすることがあります。

通常、コマンドプロンプトからPythonを起動しようとすると、パスが通っている最初のpython.exeが起動してしまいます。もちろん、その時々でパスを書き換えたり、フルパス指定したりすれば希望のバージョンのPythonを起動できますが、面倒です。

こういう場合に、Pythonの公式が用意している、Windows環境向けのPython切り替えソフト「Pythonランチャー(py.exe)」が便利ですので紹介します。

Pythonランチャー(py.exe)とは

Pythonランチャーは、Pythonの公式がWindows環境向けにリリースしているソフトです。複数のバージョンのPythonをインストールしている環境でも、任意のバージョンを指定してPythonインタープリターを起動したり、Pythonスクリプトを実行させたりできます。ここで言う「バージョン」とは、同じメジャーバージョン・マイナーバージョンの「64ビット版/32ビット版」の違いも含みます。

Python 3.3以降、Pythonをデフォルト設定でインストールすると、Pythonランチャーも一緒にインストールされます。

Pythonランチャーの実体はC:\Windows\py.exeです。拡張子.pyなども、Pythonランチャー py.exeに関連付けされます。

通常、Pythonインタープリターを使用する場合は、コマンドプロンプトに「python」と入力して、パスの通っているpython.exeを起動すると思います。Pythonランチャーをインストールしている環境では、python.exeにパスを通す必要はありません。インタープリターの起動も、スクリプトの実行もpy.exe経由で行います。

ちなみにPython 2系をインストールする際、デフォルトで「.pyファイルの関連付けを行う」の設定がオンになっています。これだとPythonランチャーへの関連付けが外れてしまいますので、オフに変更してインストールしてください。

Pythonランチャーの使い方

コマンドプロンプトを開いて、py --helpと入力すると、Pythonランチャーの使い方が表示されます。

C:\>py --help

Python Launcher for Windows Version 3.8.4150.1013

usage:
py [launcher-args] [python-args] script [script-args]

Launcher arguments:

-2     : Launch the latest Python 2.x version
-3     : Launch the latest Python 3.x version
-X.Y   : Launch the specified Python version
     The above all default to 64 bit if a matching 64 bit python is present.
-X.Y-32: Launch the specified 32bit Python version
-X-32  : Launch the latest 32bit Python X version
-X.Y-64: Launch the specified 64bit Python version
-X-64  : Launch the latest 64bit Python X version
-0  --list       : List the available pythons
-0p --list-paths : List with paths

(以下、python.exeのヘルプが続きますが、省略)

usageを訳すと、こんな感じだと思います。XやYには、起動したいバージョンを数値で指定します。後の項で、より具体的な使用方法を説明します。

使い方:
py [Pythonランチャー引数] [Python(python.exe)引数] スクリプトのパス [スクリプト引数]

Pythonランチャー引数:

-2     : Python 2.x系の最新版を起動する
-3     : Python 3.x系の最新版を起動する
-X.Y   : 指定したバージョンのPythonを起動する
     上記は、適合する64bit版Pythonがあれば、基本的に64bit版を起動します。
-X.Y-32: 指定したバージョンの32bit版Pythonを起動する
-X-32  : Python X系の32bit版Pythonを起動する
-X.Y-64: 指定したバージョンの64bit版Pythonを起動する
-X-64  : Python X系の64bit版Pythonを起動する
-0  --list       : 利用可能なPythonバージョンのリストを表示する
-0p --list-paths : 利用可能なPythonバージョンとパスのリストを表示する

インストール済みのPython一覧を表示するには

インストール済みのPython環境の一覧を表示するには、py -0p(←ゼロ・ピー)やpy --list-pathsを実行します(パスも表示する場合)。

C:\>py -0p
Installed Pythons found by py Launcher for Windows
 -3.8-64        C:\Users\ユーザー名\AppData\Local\Programs\Python\Python38\python.exe *
 -3.8-32        C:\Users\ユーザー名\AppData\Local\Programs\Python\Python38-32\python.exe
 -3.7-64        C:\Users\ユーザー名\AppData\Local\Programs\Python\Python37\python.exe
 -3.7-32        C:\Users\ユーザー名\AppData\Local\Programs\Python\Python37-32\python.exe
 -2.7-32        C:\Users\ユーザー名\AppData\Local\Programs\Python\Python27\python.exe

上記の例では、5つのバージョン(32bit/64bitの違いを含む)のPythonがインストールされていることが分かります。-3.8-64の末尾にアスタリスクが付いていますが、これはデフォルトで起動するバージョンであることを示します。

Pythonインタープリターを起動するには

通常、Pythonインタープリターを起動する場合は、コマンドプロンプトなどでpythonと入力して起動すると思います。対して、Pythonランチャーをインストールしている環境ではpyと入力すれば起動します。

C:\>py
Python 3.8.4 (tags/v3.8.4:dfa645a, Jul 13 2020, 16:46:45) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

前述の通り、私の環境ではPython 3.8の64bitがデフォルトになっていますので、それが起動しました。

同様に、-3.7を指定すると、3.7(の64bit版)が起動します:

C:\>py -3.7
Python 3.7.8 (tags/v3.7.8:4b47a5b6ba, Jun 28 2020, 08:53:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

また、-3-32を指定すると、3系で32bitの最新版である3.8 32bitが起動します:

C:\>py -3-32
Python 3.8.4 (tags/v3.8.4:dfa645a, Jul 13 2020, 16:30:28) [MSC v.1926 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

-2と指定すれば、2系の最新版が起動します(今回の例の場合、2系は2.7 32bitしか入れていませんので、それが起動しました):

C:\>py -2
Python 2.7.17 (v2.7.17:c2f86d86e6, Oct 19 2019, 20:49:36) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

ちなみに、インストールしていないバージョンを指定すると、「インストールされていない」とエラーになります。

C:\>py -2-64
Python 2-64 not found!
Installed Pythons found by py Launcher for Windows
 -3.8-64 *
 -3.8-32
 -3.7-64
 -3.7-32
 -2.7-32

Requested Python version (2-64) not installed, use -0 for available pythons

また、Pythonランチャーの引数に続いてスクリプトのパスを指定すると、そのスクリプトが実行されます。その際、後述のシェバンよりも、こちらのPythonランチャー引数の方が優先されます。

スクリプトごとにPythonバージョンを指定するには

シェバンを使ったバージョンの指定

Pythonスクリプトを作成して、関連付けに基づいて実行すると、基本的にはデフォルトのPythonで実行されます(今回の例では3.8.4 64bit)。

ただ、スクリプトごとに使用しているライブラリが異なって、使いたいバージョンも違うかもしれません。そのような場合には、スクリプトのシェバンでPythonのバージョンを指定します。(シェバンとは、スクリプトの1行目に書くもので、そのスクリプトの実行環境を指定するものです。Unix系OSのシェルスクリプトなどでも指定します。頭に書く#!の英語圏での読み「hash bang」から省略して「shebang」と呼ぶようになったらしい)

試しに、このようなスクリプトを用意してみます。このスクリプトは、単に実行中のPythonのバージョンを表示するだけのものです。(Pythonの公式ヘルプから引用)

#!python
import sys
sys.stdout.write("hello from Python %s\n" % (sys.version,))

Pythonランチャーにスクリプトパスを渡すと、スクリプトを実行できます。すると次のような出力が帰ってきます。(Pythonランチャーをインストールしている環境では、拡張子.pyはPythonランチャーに関連付けられていますので、ファイル名だけ指定したり、ダブルクリックした場合でも同様の挙動を示します)

C:\>py sample.py
hello from Python 2.7.17 (v2.7.17:c2f86d86e6, Oct 19 2019, 20:49:36) [MSC v.1500 32 bit (Intel)]

Python 2系で実行されました。インタープリターを起動する際、単にpyと打った場合はPython 3系の最新64bit版が起動しましたが、それと対照的です。これは、Linuxなどの環境では、pythonコマンドはPython 2系を、python3コマンドはPython 3系を表すことが多いため、Linuxなどとの互換性からこのような仕様になっているようです。

なので、シェバンを#!python3に書き換えると、Python 3系の最新版で実行されます:

C:\>sample.py
hello from Python 3.8.4 (tags/v3.8.4:dfa645a, Jul 13 2020, 16:46:45) [MSC v.1924 64 bit (AMD64)]

同様に、シェバンを#!python3.7に書き換えると、3.7の64bit版で実行されます:

C:\>sample.py
hello from Python 3.7.8 (tags/v3.7.8:4b47a5b6ba, Jun 28 2020, 08:53:46) [MSC v.1916 64 bit (AMD64)]

シェバンを#!python3-32に書き換えると、3系32bit版の最新で実行されます:

C:\>sample.py
hello from Python 3.8.4 (tags/v3.8.4:dfa645a, Jul 13 2020, 16:30:28) [MSC v.1926 32 bit (Intel)]

ちなみに、シェバンをタイプミスして#!pyhton3と入力すると、起動しません:

C:\>sample.py
Unable to create process using 'pyhton3 "C:\sample.py" '

また、シェバンの行を削除すると、インタープリター起動時と同様、デフォルトバージョン(最新の64bit)で実行されます:

C:\>sample.py
hello from Python 3.8.4 (tags/v3.8.4:dfa645a, Jul 13 2020, 16:46:45) [MSC v.1924 64 bit (AMD64)]

さらに、インストールしていないバージョンを指定して、シェバンに#!python2-64と書くと、「インストールされてない」とエラーとなります:

C:\>sample.py
Requested Python version (2-64) is not installed

Linuxなどへの移植性を考えたシェバンの書き方

ところで、シェバンは元々Unix系OSのシェルスクリプトで使われてきたと書きました。Pythonスクリプトも同様で、Unix系OSではシェバンで指定されたPythonで実行されます。

Linuxなどへの移植性を考えると、Linuxで実行するためのシェバン、例えば#!/usr/bin/python3.7などを指定したいかもしれません。

その場合は、Linuxを想定したPython実行ファイルのパスを指定してあげればOKです。例えば、

#!/usr/bin/python3.7
import sys
sys.stdout.write("hello from Python %s\n" % (sys.version,))

というようにシェバンを書いて実行すると、予想通り3.7の64bit版で実行されます:

C:\>sample.py
hello from Python 3.7.8 (tags/v3.7.8:4b47a5b6ba, Jun 28 2020, 08:53:46) [MSC v.1916 64 bit (AMD64)]

これは、PythonランチャーがLinux風のシェバンも読み取って、適切なバージョンで実行してくれるからのようです。

ビット数まで指定する場合は、シェバンを#!/usr/bin/python3.7-32とすればOKです:

C:\>sample.py
hello from Python 3.7.8 (tags/v3.7.8:4b47a5b6ba, Jun 28 2020, 07:55:33) [MSC v.1916 32 bit (Intel)]

ただし、ビット数まで指定したシェバンでは、Linux側ではうまく実行できないと思いますので、おすすめしません。

ここまでをまとめると、特に理由がない限り、シェバンは#!/usr/bin/python3を指定するのがよいのではないかと思います。(WindowsならPython 3系の最新版で、Linuxではシステムにインストールされている/usr/bin/python3で実行してくれる。単に#!python3でも大丈夫かもしれない)

このあたりに関しては、公式ヘルプのこちらの部分に説明があります。

シェバンより、Pythonランチャー引数が優先される

スクリプト中にシェバンを書いても、実行する際、Pythonランチャーにバージョンを指定する引数を与えた場合は、そちらが優先されます。

例えば、このようなスクリプトを用意します:

#!/usr/bin/python3.7-32
import sys
sys.stdout.write("hello from Python %s\n" % (sys.version,))

実行する際、単にPythonランチャーにスクリプトパスを与えると、シェバンに書かれているバージョンで実行されます:

C:\>py sample.py
hello from Python 3.7.8 (tags/v3.7.8:4b47a5b6ba, Jun 28 2020, 07:55:33) [MSC v.1916 32 bit (Intel)]

インタープリター起動時と同じように、バージョンを指定する引数を与えると、引数の方が優先されます:

C:\>py -2 sample.py
hello from Python 2.7.17 (v2.7.17:c2f86d86e6, Oct 19 2019, 20:49:36) [MSC v.1500 32 bit (Intel)]

pipを使用するには

Pythonのパッケージマネージャーであるpipを利用する際は、注意が必要です。というのも、複数のバージョンのPython環境がインストールされていますので、「どのバージョンのPython環境にインストールするか」を指定してあげないといけません。

デフォルトバージョンのPython環境にnumpyをインストールする場合は、py -m pip install numpyというように、バージョンを指定せずにpipコマンドを実行すればOKです。この場合、-m以降の引数は、python.exeに対して与える引数として扱われます。

C:\>py -m pip install numpy
Collecting numpy
  Downloading numpy-1.19.0-cp38-cp38-win_amd64.whl (13.0 MB)
     |████████████████████████████████| 13.0 MB 3.3 MB/s
Installing collected packages: numpy
  WARNING: The script f2py.exe is installed in 'C:\Users\ユーザー名\AppData\Local\Programs\Python\Python38\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed numpy-1.19.0

パスが通っていない、と警告が出ていますが、無視してよいでしょう。

対して、古いバージョンの環境にパッケージを足す場合は、バージョンを指定する引数を追加し、py -3.7-32 -m pip install numpyとします。このとき、-3.7-32の部分はPythonランチャーに対する引数で、-m以降はpython.exeに対する引数として扱われます。

C:\>py -3.7-32 -m pip install numpy
Collecting numpy
  Downloading numpy-1.19.0-cp37-cp37m-win32.whl (10.9 MB)
     |████████████████████████████████| 10.9 MB 6.4 MB/s
Installing collected packages: numpy
  WARNING: The script f2py.exe is installed in 'C:\Users\ユーザー名\AppData\Local\Programs\Python\Python37-32\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed numpy-1.19.0

まとめ

軽い覚え書き記事として書き始めたら、すごい重量級の記事になってしまいました。

簡単にまとめると、下記の通りです。

インタープリターの起動

コマンドプロンプト上で下記の通り、コマンドを実行する。

最新版でPythonインタープリターを起動:
py

指定したバージョンでPythonインタープリターを起動(64bitなら、ビット数は省略可):
py -3.7-32

シェバンを無視してバージョンを指定してスクリプトを実行:
py -3.7 script.py

スクリプトのシェバンに指定

スクリプト1行目のシェバンに下記の通り記載すれば、(実行時にバージョンを指定しない限り)シェバンに書かれたバージョンのPythonで実行される。

最新版のPythonで実行:
#!python3
注意:「python」としてしまうと、Python 2系で実行されてしまうので気をつける

指定したバージョンのPythonで実行:
#!python3.7-32

Linuxなどへの移植を考えて、Linux環境でのフルパスで指定:
#!/usr/bin/python3

同じく、特定のバージョンを指定:
#!/usr/bin/python3.7
注意:Windows向けであればビット数指定もできるが、おそらくLinux側では動かない

pipでパッケージを追加

コマンドプロンプトで下記のコマンドを実行する。(例として、numpyをインストール)

最新版のPython環境にパッケージを追加:
py -m pip install numpy

指定したバージョンのPython環境にパッケージを追加:
py -3.7-32 -m pip install numpy

参考サイト

この記事は、これらのページを参考にさせていただきました。