Python 3.3 未満しか持ってない場合 Python Launcher for Windows はどしたら?

前々からずーーっっと気になってはいたんだよな、これ。

ここで説明されている Python Launcher for Windows、Python 3.3 以上を一つでもインストールしていれば、複数環境共存しててもとっても楽。アタシの PC な場合:

 1 me@host: ~$ py -2
 2 Python 2.7.9 (default, Dec 10 2014, 12:28:03) [MSC v.1500 64 bit (AMD64)] on win32
 3 Type "help", "copyright", "credits" or "license" for more information.
 4 >>>
 5 me@host: ~$ py -3
 6 Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)] on win32
 7 Type "help", "copyright", "credits" or "license" for more information.
 8 >>> ^Z
 9 me@host: ~$ py -3.2
10 Python 3.2.5 (default, May 15 2013, 23:07:10) [MSC v.1500 64 bit (AMD64)] on win32
11 Type "help", "copyright", "credits" or "license" for more information.
12 >>> ^Z
13 
14 me@host: ~$ py -3.1
15 Requested Python version (3.1) not installed
16 me@host: ~$ py -3.3
17 Python 3.3.5 (v3.3.5:62cf4e77f785, Mar  9 2014, 10:35:05) [MSC v.1600 64 bit (AMD64)] on win32
18 Type "help", "copyright", "credits" or "license" for more information.
19 >>> ^Z
20 
21 me@host: ~$ py -3.4
22 Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (Intel)] on win32
23 Type "help", "copyright", "credits" or "license" for more information.
24 >>> ^Z
25 
26 me@host: ~$ py -3.5
27 Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)] on win32
28 Type "help", "copyright", "credits" or "license" for more information.
29 >>> ^Z
30 
31 me@host: ~$

しかも実体(c:/Python27/ とか)にパスを通してなくてもいいのが良い。

そうなんだけれど、たぶん Python2.7 と Python3.2 しか持ってない、みたいな哀れなケースてのも、想像するに結構あるんじゃないかと思う。個人なら気にせずばんばんインストールしちゃえ、て話だけれど、企業ユースで「逐一何するにも許可がいる」みたいな場合、簡単には新しい Python 3.x を導入出来ない、なんてのは想像出来る。

以前ワタシは「そもそも 3.0~3.1 は非推奨」と書いた。これは 2.7 が長期間サポートされることを踏まえた 3.x 系の「2.7 への再歩み寄り」が起こったことを踏まえたもの。つまり「3.x 系の 2.x との非互換性は 3.0、3.1 の方がムゴい」てこと。要するにそれを書いたときはこのランチャーの存在は踏まえてないわけなんだけれど、まぁそこは「Windows だけの話をしてたわけじゃない」んでね。

軽く検索してみるも、バックポートはなさげ。

うーん。とりあえずさ、PC/launcher.c はひっじょーにシンプルなコンソールアプリケーションになってて、ネイティブな VC なら簡単にビルド出来るのね。Python 依存のことは何にもしてなくて、コードは完全に独立してる。どうしてもってんならこれを自力でビルドして、「パスの通った場所」に置けばいいんじゃないかな。(ちなみに本家は 3.5 までは c:/Windows 直下、3.6 からはまさに「パスが通った場所」に置く。)

まぁこういう困り方をしている状況自体がそんなにはないのかなぁ、と思うも、いたらいたできっと悩む人もおられるんだろうから、一応書いてみた。

ビルドの仕方? 気が向いて、かつ、「少しは悩むのかも」と思えば追記する、かも。不慣れな人が悩むとしたらリンクするライブラリの件だけだろうと思う。


2017-08-12追記:
まぁなんというか「py.exe だけは許される」なんてケース自体相当稀なわけで「誰の役に立つんだ」と思いつつも一応やってみた、ビルド。

まず、少なくとも本日時点のマスタブランチのものは壊れてる。起動に成功したり失敗したりと安定しない。何か大改造入れてる途中だろうね。なので 3.5 リリース版3.6 リリース版 のいずれかを使うといい、今のところ。

ビルドは本家のプロジェクトファイルによれば一番シンプルにコマンドラインからビルドするにはこれだけ:

1 me@host: ~$ cl -c -nologo -MD -D_WIN32 launcher.c
2 me@host: ~$ link -nologo -subsystem:console launcher.obj advapi32.lib version.lib shell32.lib -out:py.exe

と思う。(本来はアイコン(launcher.ico)を取り込む。やりたい人はやれば? rc.exe のお出番、かな。)

vcxproj を読み込んで Visual Studio IDE (or msbuild) がどんな魔法を仕掛けるのか全貌は知らないので本当にこれだけかは正直良くはわからない。特に

  1. <CharacterSet>MultiByte</CharacterSet>-D_MBCS-D_DBCS、あるいは -D_UNICODE を意味するのかどうか
  2. platform=x64 と -D_M_X64 との関係は?

についてが良くわからない。VC9 まではこれら C プリプロセッサマクロは暗黙ではなく全部プロジェクトファイル内に書くもんだったんでわかりやすかったんだけどね、VC10 以降のはImport してるシステムファイル全部読まないことにはわからないんだよね。(実は今まさにそんなことを研究中だったりするのだけれど。)

ひとまずワタシの PC にインストールされている py.exe は 32bit 版アプリケーションになっていて、なので「あえて -D_M_X64 はいらないのかな」と思ってそうしなかったが、コンパイラは 64bit 用なので、付けるのが正解なのかも。

そういうわけで、「ひょっとしたらこっちが正解かも」はこれ:

64bit 版コンパイラを使う場合。
1 me@host: ~$ cl -c -nologo -MD -D_WIN32 -D_UNICODE -DUNICODE -D_M_X64 launcher.c
2 me@host: ~$ link -nologo -subsystem:console launcher.obj advapi32.lib version.lib shell32.lib -out:py.exe

あとどのコンパイラを使うかによっても、ハマる可能性はないではないのかも。2つ。「VC ランタイム」関連が一つ。いわゆる「再頒布可能モジュール」と呼ばれてる例のアレ。開発環境持ってるんだから起こらないでしょ、てもんでもなくて、ビルドだけ出来るパターンはある。もう一つが manifest の問題があって。アタシが持ってるコンパイラでビルドすればこれらどちらも起こらなかったけれど、もし後者が起こるようなら「manifest 埋め込み」とかで検索してみればいいと思う。(あるいは distutils 経由でビルドする場合ここらへんの面倒はみてくれるので、出来る人ならそうするのが手っ取り早い。)

なお、この「よくわからん」以外ではいくつかプリプロセッサマクロを定義出来るが、わかる人はソース読んでくれ、でもいいか? と言いたいところだけれど一応…。

まず、-DWINDOWS はあればいいかもね、これはコマンドライン用じゃなく「*.py クリック時」に動くやつのはず(pyw.exe)だけれど、関連付けとか自力でやらんといかんだろうし、個人的に「*.py クリックして何がしたいんだ」と 99% のシチュエーションでは思う。いらんじゃないの?

-DSCRIPT_WRAPPER は一般ユーザ向けではなくこれは setuptools が使う用。今の場合はそこまではやらんでいいのでわ。

-DSKIP_PREFIX は…、shbang の解釈の仕方がこれを付けるとちょっと変わる、みたい。

-DSEARCH_PATH を付けないと、環境変数 PATH に従わないのが仕様。原則としてこれがまさに「ポリシー」なので従うのが良いと思うが、そうしたい事情があるなら -DSEARCH_PATH を付けると良いかもね。