$$ \def\v{\boldsymbol} \def\m{\boldsymbol} \def\trans{^\mathsf{T}} \def\inv{^{-1}} \def\bmat{\begin{pmatrix}} \def\emat{\end{pmatrix}} \def\diag{\operatorname{diag}} \def\tr{\operatorname{tr}} \def\ad{\operatorname{ad}} \def\Ad{\operatorname{Ad}} \def\E{\operatorname{E}} \def\det#1{| #1 |} \def\her{^\mathsf{H}} \def\wed{\wedge} \def\given{\mid} \def\defeq{\triangleq} \def\Ys{{\cal Y}} \def\argmin{\mathop{\mathrm{argmin}}} \def\argmax{\mathop{\mathrm{argmax}}} \def\blockdiag{\mathop{\mathrm{blockdiag}}} \def\inner#1{\langle #1 \rangle} $$

プログラミング演習用のポータブルな Python + VSCode + Git 環境

工学部機械系2年生向けのプログラミング演習科目のために,Windows 上で zip ファイルを展開するだけで使えるようになる Python + VSCode + Git の実行環境を作った.このエントリでは,技術的な要点と実際に運用してみてわかったことをまとめる.

背景

工学部機械系の2年生向けのプログラミング演習科目を昨年度から担当していて,前任者から引き継いだ C 言語による内容を,今年度から Python によるものに全面更改した.

https://web.tohoku.ac.jp/kc_kyomu/computer_seminar1/py/textbook_ja/

プログラミングの演習を Bring Your Own Device (BYOD) でやると,だいたい最初の1~2週はインストール&環境設定大会に費やされ,なかなか本題に入れない.特に,リモート授業だとトラブル対応も容易ではない.これを何とかしたかった.

Processing では,zip ファイルを取ってきて展開するだけでエディタ等も含めてすぐ使えるようになっていて,初学者が取り組み始める際の障壁が低い.これに近いものを作りたい.

(だったらなぜ授業を Processing でやらないのか,という疑問が生じるところだが,諸条件いろいろ考慮して Python に決めた.そこに踏み込むと長くなるので別の機会に譲りたい)

zip ファイルを展開した後は,そのフォルダをどこに移動しても使えることが望ましい.また,他の授業で使っている環境や個人で使っている環境に影響を及ぼしたり,逆にそれらに影響されたりしたくない.そのような移動可能で閉じた環境をこのエントリでは「ポータブル」と呼んでいる.

学生は入学時に Windows 機を購入するよう指示されているので,対象環境は Windows に限定した.が,例年 Mac 使いも各クラスに数人はいて,今後も同様だと思われるが,自力で同様の環境を構築してもらう方針.(実際何とかなっている模様)

仕組み

具体的な構築方法については テキストの付録B を,スクリプトや設定ファイルの詳細内容については 配布サイト にある zip ファイルの中身をご覧頂くとして,ここでは基本的な仕組みとその背景を書く.

構成要素

WinPython

WinPython は Windows 用の Python ディストリビューションで,もともとポータブル.

MinGit

Git for Windows のポータブル版には PortableGit と MinGit がある.PortableGit が 300 MB くらいを占めるのに対して MinGit は 50 MB くらいで,その分 UI まわりがざっくり省略されている.例えば Git Bash や git-gui などは含まれない.今回は基本的に VSCode の中から使ってもらうことにしているので,MinGit を選んだ.

(なお PortableGit の方はインストール後に MSYS2 の rebaseall が走る仕組みのようで,今回のように展開済みのものを他の環境に配布する用途にそもそも使えるのかどうか未確認)

VSCodium

VSCode は,実行ファイルのあるフォルダの中に data フォルダを掘ってから起動すると ポータブルモードになる.ただし,マイクロソフト公式の Visual Studio Code は再頒布が許されていないので,オープンソース版のビルドである VSCodium を使うことにした.

VSCode の設定

VSCode の中から WinPython や MinGit を使えるようにする必要がある.

WinPython には scripts/env_for_icons.bat という環境設定をしてくれるバッチファイルがあり,これを call してから VSCode を起動するようなバッチファイル (vscode_cs1.bat) を作っておいて,VSCode は常にこれを経由して起動することにする.追加で設定したい環境変数は settings/winpython.ini で指定できる.

ただし,ユーザの元の環境に他の Python がインストールされている場合,そちらが優先されてしまう場合がある (どうもルールがよくわからないのだが,単に環境変数 PATH での出現順というわけでもないらしい).そのため VSCode の settings.json でも python.defaultInterpreterPath と python.pythonPath を指定しておく.このうち python.pythonPath は既に非推奨で python.defaultInterpreterPath に一本化すべきとされているのだが,どうも片方だけだとうまく動かない場合があった.念のため両方入れてある.

MinGit については,基本的には winpython.ini で PATH を設定しておけばよい.こちらも念のため VSCode の settings.json で git.path を設定しておこうかという気分になるのだが,どういうわけか git.path の設定値には環境変数を埋め込めないので,ポータビリティを確保できない.しかたないので PATH に任せている.

MinGit に関してもう一つ考慮が必要なのは ~/.gitconfig の扱いで,特に email と name の設定がないと commit ができないので何らかの値をセットしておく必要がある.しかしユーザ環境は汚したくないので,配布物の中に home フォルダを別途用意して,環境変数 HOME がそこを指しておくようにした.そこに .gitconfig を置き,ダミーの email と name を書き込んでおく.

あとは,VSCode拡張機能を入れたり,settings.json に設定を加えたり,pip でいろいろインストールしたりしてから zip にまとめて配布すればよい.とはいえ,操作履歴などの各種キャッシュが残ったまま配布するのも気持ち悪い.そのため,VSCodium フォルダの data/user-data はいったん削除して,data/user-data/User/settings.json だけ復元してから zip 化している.

既知の問題

ユーザ環境を汚さないことを目指してはいるのだが,残念ながら完全ではない.

VSCodium/Dictionaries

なぜかよくわからないが,ユーザフォルダの AppData/Roaming/ に空のフォルダ VSCodium/Dictionaries が掘られる.実害はなさそうなので放置.

pip の --user オプション

ユーザが pip に --user オプションをつけて実行すると (当然ながら) ユーザ環境にインストールされてしまう.

わざわざ --user をつけているのだからそれはユーザの意図通りということで問題なかろうともいえそうだが,「どこかで見かけた説明を深く考えずにコピーペーストしたら --user つきだった」というケースも大いにあり得るのでどうしたものかというところ.

ここまで書いていて気づいたが,VSCode が pip パッケージの追加をお勧めしてくる場合があって,勧めに乗るとデフォルトでは pip が --user つきで実行される.settings.jsonpython.globalModuleInstallation: true を入れておく方がよいかもしれない.

アンチウィルスソフトウェア

おそらくファイルの配置などが影響しているのだと思うが,アンチウィルスソフトウェアに妙に引っかかる.

「実行をブロックしました」などと報告してくるのはまだいいが,McAfee などは何も言わずに勝手に隔離したりしてくれるので本当に困る.

運用時のあるあるを早く言いたい

事前にいろいろな筋から聞いていたことではあるのだが,スマートフォンネイティブな世代と我々旧人類では「常識」の範囲に大きな隔たりがあって,そこに注意しないと必要な情報をうまく伝えることができない.というか,どこに隔たりがあるかを事前に認識するのが難しいので,蓋を開けてみて初めて「あー,そこでハマるのか」となる場合が多い.

zip ファイルの展開は失敗しがち

今回配布する zip ファイルは 300 MB くらいあり,展開すると 1 GB くらい,ファイル数は 3 万個くらいになる.このくらいの規模の zip ファイルになると,旧人類であれば Windows 標準の zip 展開機能を使おうという気にはならないものだが,この「Windows 標準の unzip は使い物にならない」という常識はもちろん自明なものではない.明示的に伝えないと多くのユーザがハマるようだ.

Windows 標準の unzip はとにかく遅い.さらに致命的なのは長いフルパス名を扱えないことで,今回の zip ファイルには 200 文字超のパス名のものが含まれるため,展開先によっては失敗する.

というかマイクロソフトがなぜこの問題を放置しているのか全く理解に苦しむ.

バッチファイル経由の起動は忘れられがち

前述の通り,VSCode はバッチファイルを経由して起動することにしている.しかしこれをすっ飛ばして VSCode を直接起動してしまうケースがかなりの頻度で見られた.どうも初回だけバッチファイルで実行すればよいという誤解が生じているようで,つまりは説明不足だった.

配布物の中の VSCodium.exe はちょっとわかりにくいところにあるのでこれを直接起動してしまう人はあまりいないと思うが,他の授業等でユーザ環境に VSCode をインストール済みの場合に,普段通りそちらの VSCode を起動してしまうケースがよく見られた.この場合 (ユーザ自身が自力で設定していない限りは) 環境変数 PATH や HOME が適切に設定されていないため,うまく動かない.

これを見分けるにはタイトルバーを見るのが早い.配布物を起動している場合は VSCodium と表示されるはずなので,もし Visual Studio Code と表示されていたら違うものが起動されている.

ちょっと違うケースとしては,正しくバッチファイル経由で起動した VSCodium をタスクバーにピン留めして,次回以降そこから起動してしまうというものがある.タスクバーからの起動ではバッチファイル経由にならないので期待通りに動かない.この場合はタイトルバーでは見分けられないので判断が難しい.

「フォルダを開く」指示は見逃されがち

テキストでは,Python ソースファイルを置くフォルダを VSCode の File → Open Folder (フォルダを開く) で開いてから,ソースの編集,実行,git add と commit などをするように指示している.

ところが,Open Folder ではなく Open File でソースファイルを直接開いてしまったり,別のフォルダ (例えば上位のフォルダだったり,ホームディレクトリだったり) を開いてしまったりするケースが散見される.その結果,ソースファイルの編集・実行はできるのだが,Git まわりで混乱が生じてしまう.

これも VSCode のタイトルバーに注目することである程度判断できる.タイトルバーには本来「ファイル名 - フォルダ名 - VSCodium」と表示されるはずだが,Open Folder をしていなければフォルダ名の表示がなくなるし,違うフォルダを開いているならばそのフォルダ名が表示される.

この問題の厄介なところは,「Git がうまく動かない」と本人が気づいた時点では正しいフォルダが開かれているかも知れないという点である.過去に正しくないフォルダで commit してしまったせいで,現在は正しいフォルダを開いているにも関わらず (というか,正しいフォルダを開いているからこそ) 昨日したはずの commit が見当たらないとか,大量 (5000以上) の変更点が検出されるとかの事象が生じる.ユーザ自身に「現在開かれているフォルダ」を意識させる必要があるように思うのだが,おそらく,スマートフォン世代はこれに慣れていない,というかフォルダという概念自体が希薄なように思う.