Umi Uyuraのブログ

プログラミング関連の作業ログ

FastCopyをwingetでインストールするときにインストール先を指定する

FastCopyをwingetでインストールするときにインストール先を指定する

Windows系最速(? ※公式のまま)のファイルコピー&バックアップツール FastCopy ですが、wingetを使って普通にインストールするとホームディレクトリの直下に C:\Users\<user>\FastCopy のようにインストールされます。(インストーラを手動で実行すればインストール場所を指定できます)

個人的にホームディレクトリ直下にプログラムを置きたくなかったので、場所を変更することにしました。

wingetでは --location オプションを与えることでインストール先を指定することができます。

Program Filesにはインストールできず

はじめはアプリケーションのインストール先として一般的な C:\Program Files にインストールしようとしました。

>winget install FastCopy --location "C:\Program Files\FastCopy"

ところがこの場合、実際にインストールされた場所は C:\Program\FastCopy となっていました。

手動でインストーラを実行した場合は問題なかったので、どうやらwinget経由してFastCopyインストーラにパスが渡されるときに、スペースが含まれていると、そこで途切れてしまっているようです。

%LOCALAPPDATA% にインストールする

というわけで、スペースを含まないパスにインストールした方が良さそうなのだけれど、どこにしたものかと考えていたときに、以下の記事を見つけました。

LocalAppData にアプリケーションをインストールするという選択 - meg_nakagamiの日記

少し調べてみたものの、明確に %LOCALAPPDATA% の用途について説明されているドキュメントを見つけられませんでしたが、たしかに最近のアプリケーションを見ていると %LOCALAPPDATA% にインストールされているものも多いようなので、ここにインストールすることにしました。

>winget install FastCopy --location "%LOCALAPPDATA%\FastCopy"

%LOCALAPPDATA%C:\Users\<user>\AppData\Local とスペースを含まないパスに展開できるので、wingetでのインストールも意図通り C:\Users\<user>\AppData\Local\FastCopy にインストールできました。

便利な使い方

インストール先のパスを環境変数 PATH に追加しておくことで、コマンドプロンプトからも利用することができるようになります。

個人的にはコピーよりも削除で利用することが多く、 doskey で以下のようなマクロを用意しています。

fastrm=fastcopy /cmd=delete /auto_close $1

Node.jsのnode_modulesをまっさらにしたいときなど fastrm node_modules と実行することで削除できます。

ついでに

C:\Users\<user>\AppData には Local 以外に RoamingLocalLow というフォルダがありますが、どういう使い分けなのか気になったところ、以下の記事が参考になりました。

猫科研究所 - Roaming, Local, LocalLow

WSL + Homebrewの環境でMkDocsがModuleNotFoundError: No module named '_ctypes'

Markdownベースでドキュメントサイトを作ることができるPython製のツール MkDocs を使おうとしたところ、 ModuleNotFoundError が発生してコマンドが動かない問題が出てしまいました。

原因はHomebrew (Linuxbrew)で入れていたライブラリで、それを除去してPythonを入れ直すことで解消したので、経緯をメモしておきます。

環境

エラーが出た状況と考察

WSL (Ubuntu)環境で、venvで作ったPython仮想環境に pip install mkdocs でMkDocsをインストールしました。

インストール自体は問題なかったものの、 mkdocs new を実行時にエラーが発生しました。

$ mkdocs new
Traceback (most recent call last):
...
ModuleNotFoundError: No module named '_ctypes'

参考になったのは Pythonでの ctype の依存関係エラー対策の備忘録 / ModuleNotFoundError: No module named ctypes 対策 | simple blog という記事でした。

WSL上にPythonをインストールするにあたり、asdfとそのプラグインであるasdf-pythonを使っています。

asdf-pythonの内部ではpyenvが使われており、pyenvはPythonのバージョンをインストールするときにソースコードからビルドをおこないますが、その際環境に応じて事前に必要なパッケージをインストールしておく必要があります。

Suggested build environment

そういえば、WSL上にPython環境を構築するとき、Homebrewも導入していたこともあり、一度Linuxbrew用の指定パッケージを入れてしまっていました。

umi-uyura.hatenablog.com

ただ、これではうまくいかず、Ubuntu用の指定パッケージを入れることでasdf-pythonが使えるようになりました。

そのため、もしかするとこのときに入れてしまったLinuxbrew用のパッケージが影響しているのではないかと考えました。

Homebrew (Linuxbrew) の依存関係を取り除く

先のpyenvのサイトによると、Linuxbrewの場合は以下のパッケージが指定されています。

brew install bzip2 libffi libxml2 libxmlsec1 openssl readline sqlite xz zlib

よって、これらを削除すれば良いかなと思いましたが、Homebrewの他のアプリケーションなどで使われているものがあるかもしれないので、念のため調べてみます。

参考: Homebrew でパッケージの依存関係を調べる方法 - Qiita

brew uses <package> --installed で、そのパッケージがインストールされている他のパッケージから使われているかどうかを調べることができるとのこと。

$ brew uses bzip2 --installed
$ brew uses libffi --installed
autogen gnutls guile guile@2 libxmlsec1 p11-kit
$ brew uses libxml2 --installed
autogen gettext gnutls libidn2 libxmlsec1 nghttp2
$ brew uses libxmlsec1 --installed
$ brew uses openssl@1.1 --installed
asdf autoconf automake berkeley-db gnutls libevent libxmlsec1 nghttp2 perl unbound
$ brew uses readline --installed
asdf autogen gettext gnutls guile guile@2 libidn2 libxml2 libxmlsec1 nghttp2 sqlite
$ brew uses sqlite --installed
$ brew uses xz --installed
$ brew uses zlib --installed
autogen binutils fnm gcc gettext gnutls libidn2 libxml2 libxmlsec1 nghttp2 sqlite zstd

こう見ると、依存されているものがあるのは libffi libxml2 openssl@1.1 readline zlib でした。

また、 brew deps <package> とすることで、指定パッケージが依存しているパッケージを調べることができます。

今のところ、Homebrewで使っているものとしては asdfgcc、direnv、fnm といったあたりだったので、今度はそれらが依存しているパッケージを調べてみます。

$ brew deps asdf
attr
autoconf
automake
berkeley-db
ca-certificates
coreutils
expat
gdbm
gmp
libtool
libyaml
m4
ncurses
openssl@1.1
perl
readline
unixodbc
$ brew deps gcc
binutils
gmp
isl
libmpc
mpfr
zlib
zstd
$ brew deps direnv
$ brew deps fnm
zlib

こうしてみると、 openssl@1.1 readline zlib あたりは他のものでも使っているようなので、それらはいったん残すことにして、それ以外のパッケージをアンインストールしてみることにします。

$ brew uninstall bzip2 libffi libxml2 libxmlsec1 sqlite xz
Error: Refusing to uninstall /home/linuxbrew/.linuxbrew/Cellar/libffi/3.4.2 and /home/linuxbrew/.linuxbrew/Cellar/libxml2/2.9.12
because they are required by autogen, gettext, gnutls, guile, guile@2, libidn2, nghttp2 and p11-kit, which are currently installed.
You can override this and force removal with:
  brew uninstall --ignore-dependencies bzip2 libffi libxml2 libxmlsec1 sqlite xz

libxml2 に依存しているパッケージがあるため、エラーになりました。

これを無視したい場合は --ignore-dependencies を付ければ良いようなので、オプションを付けて再実行します。

$ brew uninstall --ignore-dependencies bzip2 libffi libxml2 libxmlsec1 sqlite xz

Python再インストールとMkDocsの動作確認

これでHomebrewの不要と思われる依存関係を取り除けたので、Pythonを再ビルドするためにアンインストール&再インストールをおこないます。

$ asdf uninstall python 3.10.2
$ asdf install python 3.10.2
python-build 3.10.2 /home/<user>/.asdf/installs/python/3.10.2
Downloading Python-3.10.2.tar.xz...
-> https://www.python.org/ftp/python/3.10.2/Python-3.10.2.tar.xz
Installing Python-3.10.2...
python-build: use readline from homebrew
python-build: use zlib from homebrew
Installed Python-3.10.2 to /home/<user>/.asdf/installs/python/3.10.2

よく見ると、 python-build: use readline from homebrew のようにHomebrewのパッケージを参照しているものが出力されていました。

もしかすると、当初Pythonをインストールしたときには除去した依存関係も出力されていたのかもしれません。

Pythonインストール後、venvで仮想環境を作ってからMkDocsのインストール&実行してみます。

$ python -m venv .venv
$ . .venv/bin/activate
(.venv) $ python -m pip install mkdocs
(.venv) $ mkdocs new hoge
INFO     -  Creating project directory: hoge
INFO     -  Writing config file: hoge/mkdocs.yml
INFO     -  Writing initial docs: hoge/docs/index.md
(.venv) $ cd hoge
(.venv) hoge$ mkdocs serve
$ mkdocs serve
INFO     -  Building documentation...
INFO     -  Cleaning site directory
INFO     -  Documentation built in 0.05 seconds
INFO     -  [14:21:23] Serving on http://127.0.0.1:8000/

MkDocs、使えるようになりました。

定期メンテナンス

こうしてみると、依存関係でインストールされたものの、その後使われなくなるパッケージというのもけっこうありそうなので、そういったメンテナンスするのに以下の記事が参考になりそう。

Homebrew で使われていない formula を削除する :: by and for engineers

WSLがエラーコード4294967295で起動しない

Windows TerminalでWSLのUbuntuを開こうとしたところ、このようなエラーが出て起動してくれませんでした。

ネットワーク名が見つかりません。

[process exited with code 4294967295 (0xffffffff)]

ふだんならWindowsにログインしてWindows Terminal開けばアクセスできていました。

Windows側から wsl -l --verbose で調べてみたところ、どうやらWSLが止まっているもよう。

>wsl -l --verbose
  NAME            STATE           VERSION
* Ubuntu          Stopped         2

エクスプローラ\\wsl$ を開いて見ても、ふだんなら表示されているはずのUbuntuが消えていました。

f:id:umi-uyura:20220211225353p:plain

とりあえずWSLを起動するコマンドを打ってみます。

>wsl -d Ubuntu
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.72-microsoft-standard-WSL2 x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of ...

起動してくれました。

軽く調べてみたところ、WSLのネットワークまわりを変更したときにおこったりすることもあるようですが、直近で特にそういった操作はおこなっていなかったので、何かのタイミングによってこういうことがあるのかも。

Pythonを複数バージョンインストールしているときにwingetでアップデートしてみる

先日WindowsPythonの環境を作った際、wingetとPythonランチャーで複数バージョンのPythonを使えるようにしてみました。

umi-uyura.hatenablog.com

どうやら最近3.10系の新しいバージョンが出たようなので、自分の環境もアップデートしてみることにしました。

Python Insider: Python 3.10.2, 3.9.10, and 3.11.0a4 are now available

現行バージョン(3.10)のアップデート

winget list でインストール済のパッケージの一覧を表示すると、新しいバージョンがあるものについては「利用可能」列にそのバージョンが表示されます。

>winget list python
名前            ID                                     バージョン  利用可能    ソース
-------------------------------------------------------------------------------------
Python 3        Python.Python.3                        3.9.7150.0  3.10.2150.0 winget
Python Launcher {7DE12550-BE09-44DD-BDB4-0EC26BA89DAF} 3.10.7644.0
Python 3        Python.Python.3                        3.10.1150.0 3.10.2150.0 winget
Python 3        Python.Python.3                        3.8.10150.0 3.10.2150.0 winget

私の環境にはPython 3.10、3.9、3.8が入っているのですが、どれも利用可能なバージョンとして 3.10.2150.0 と、3.10系の最新バージョンが表示されていました。

一覧上はどの系統もIDが Python.Python.3 となっていますが、この状態でwingetでアップデートするとどうなるのか?

>winget upgrade --id Python.Python.3
複数のインストール済みパッケージが一致する入力条件を検出しました。入力内容を修正してください。
名前                   ID
-------------------------------------------------------------
Python 3               Python.Python.3
Python 3.9.7 (64-bit)  {0f0bf1a5-3ec1-459b-ab7c-916db941f50d}
Python 3.10.1 (64-bit) {af822d5e-759c-4e77-9696-3cc835cd54a9}
Python 3.8.10 (64-bit) {e9cd241b-9125-4624-9625-ff42d2f3647f}

指定したIDに一致するパッケージが複数あるということで、何やら別々のIDが表示されました。

>winget upgrade --id {af822d5e-759c-4e77-9696-3cc835cd54a9}
見つかりました Python 3 [Python.Python.3] バージョン 3.10.2150.0
このアプリケーションは所有者からライセンス供与されます。
Microsoft はサードパーティのパッケージに対して責任を負わず、ライセンスも付与しません。
Downloading https://www.python.org/ftp/python/3.10.2/python-3.10.2-amd64.exe
  ██████████████████████████████  26.9 MB / 26.9 MB
インストーラーハッシュが正常に検証されました
パッケージのインストールを開始しています...
インストールが完了しました

アップデートされたようです。

改めてインストール済Pythonの一覧を表示してみると、Python 3.10系のみアップデートされていました。

>winget list python
名前            ID                                     バージョン  利用可能    ソース
-------------------------------------------------------------------------------------
Python 3        Python.Python.3                        3.9.7150.0  3.10.2150.0 winget
Python Launcher {7DE12550-BE09-44DD-BDB4-0EC26BA89DAF} 3.10.7644.0
Python 3        Python.Python.3                        3.10.2150.0             winget
Python 3        Python.Python.3                        3.8.10150.0 3.10.2150.0 winget

>py --version
Python 3.10.2

ひとつ前のバージョン(3.9系)のアップデート

先のURLによると3.9系のアップデートも出ているようでしたので、試してみようと思ったのですが。

>winget show --versions python3
見つかりました Python 3 [Python.Python.3]
バージョン
-----------
3.10.2150.0
3.10.1150.0
3.10.150.0
3.9.7150.0
3.9.6150.0
3.9.5150.0
3.9.4150.0
...

2022/2/7時点では、winget用のパッケージとして 3.9.10 は出ていないようでした。

3.10系がでていることもあり、もしかすると3.9系の最新版はwingetに来ないかもしれないのかもと思い、公式サイトからインストーラーを落として入れてみることにしました。

https://www.python.org/downloads/release/python-3910/ からWindows installer (64-bit)をダウンロードして、インストールを実行。

そのあとで、あらためてインストール済のPythonの一覧を表示してみたところ、ちゃんと3.9系のバージョンがあがっていました。

>winget list python
名前            ID                                     バージョン  利用可能    ソース
-------------------------------------------------------------------------------------
Python 3        Python.Python.3                        3.9.10150.0 3.10.2150.0 winget
Python Launcher {7DE12550-BE09-44DD-BDB4-0EC26BA89DAF} 3.10.7644.0
Python 3        Python.Python.3                        3.10.2150.0             winget
Python 3        Python.Python.3                        3.8.10150.0 3.10.2150.0 winget

現行の最新バージョンであればwinget経由でアップデートしていけそうですが、それよりも前の系統については、必要に応じて手動でアップデートしないといけないのかもしれません。

Windows 10で使うランチャーアプリをFlow Launcherにした

macOSではAlfredを使っていましたが、Windows 10でも同じようなコマンド入力式のアプリケーションランチャーを使いたいと思い、いくつか試した結果、最近はFlow Launcherを使っています。

先日、初めてのプラグインを作ってみました。

umi-uyura.hatenablog.com

上の投稿にも書いたのですが、もともと使っていた Hain というアプリの開発が止まってしまったので、乗り換え先を探した結果、Flow Launcherにたどり着きました。

そこで、そのときに候補になったものと選定理由をメモしておこうと思います。

選定にあたっての条件

選定にあたって、個人的に以下のような条件をあげていました。

プラグインが作れる

ランチャー自体の機能としては備わっていなくても、あとで追加できるのであれば自分で作っても良いので。

UWPアプリを起動できる

Microsoft Storeでインストールしたアプリを起動できること。

Hainは対応していなかったので、ショートカットを作って特定のフォルダに集め、それをランチャーに呼び出せるようにしていました。

マルチプラットフォーム

ランチャーは自分の中では利用頻度高いアプリなので、WindowsmacOSで同じ操作感で使えるのであれば、その方が良いかもという考えもありました。

これはプラグインが作れることにも関係していて、せっかく作るのであればmacOSでも使えると良いなと思っていました。

候補と個人的感想

今回試してみたものは以下のような感じ。

※数値は2022/1/30時点

アプリ Star Fork 備考
Cerebro 7215 471 マルチプラットフォーム(Win/mac/Linux)
ueli 2222 175 マルチプラットフォーム(Win/mac)、プラグイン機能なし
Keypirinha 850 20 プラグイン豊富
PowerToys Run 67,345 3,790 PowerToysの機能の一つ、Woxベース
Wox 21,289 2,291 PowerToys Runのベース
Flow Launcher 756 53 Woxベース

Cerebro

Cerebro App – open-source productivity booster with a brain

実はHainを使っているころから目をつけていて、Hainが止まったのを知って、最初はこちらに乗り換えようとしました。

ElectronベースでマルチプラットフォームWindows/macOS/Linux)で使える点と、JavaScriptプラグインを作れる(npm経由で配布)点が魅力でした。

当時は個人でmacOSも併用していたので、プラグインを自作したときにWindowsでもmacOSでも使えると便利だなと思い、環境の共通化という観点で良さそうだなと思ったのでした。

ただ、いざ今回乗り換えようとしたところ、最新版の0.4.0は肝心のWindowsビルドに問題があるようで配布されておらず、手元でビルドしてもうまくいかなかったので、導入は断念しました。

ueli

ueli - A keystroke launcher for Windows and macOS

これもElectronベースでWindowsmacOSに対応しているランチャー。

触ってみたところ、非常に高速に動作するしUWPアプリにも対応しているので良さそうだったのですが、プラグイン機能がなかったので、残念ながら今回は見送り。

要望はあがっているようなので、いずれプラグイン作れるようになったら再度検討しても良いかもとは思っています。

Keypirinha

Keypirinha

こちらも機能豊富で、プラグインも作れるので、UWPアプリもプラグインで対応しているので良さそうかなと思ったのですが…

デフォルトのランチャー起動キーバインドCtrl + Win + K だった点は設定で変更できたのでまあ良いのですが、ランチャーに表示された機能を選択する際に Ctrl + n / p で移動ができなかった点が個人的な操作感として慣れなかったので見送りに。

PowerToys Run

microsoft/PowerToys: Windows system utilities to maximize productivity

PowerToysに付属しているランチャー機能。

そういえばそんなのあったなと思って、いろいろ迷っている間に仮で使ってみたらわりと良かったので、しばらく使っていました。

ただ、まだ公式でプラグインがサポートされていないのですが、ベースになっているWoxというランチャーアプリではプラグイン機能がサポートされているので、それならWoxでも良いかもと思って、Woxを試してみることにしました。

Wox

Wox

そんなこんなで、もうこれで決まりかなと思ってWoxをインストールしてみたのですが…

インストールした直後あたりからPCのファンが回る勢いが急激に早くなる症状が発生。

どうやら既知の問題ではあるようで、UWPアプリをインデックス化するときに問題が起きているっぽい感じ。

taking too much cpu resources · Issue #3349 · Wox-launcher/Wox

それで、このIssueのなかで、こっちでは問題でないよ、と名前が出ていたのがFlow Launcherでした。

Flow Launcher

Flow Launcher

これもWoxをフォークして開発されているもののようで、もしかしたら同じ問題が出るのではとヒヤヒヤしながらインストールしてみましたが、こちらは特にCPUがブン回ることもなく、UWPアプリも実行できました。

操作感は同じくWoxをベースにしているPowerToys Runと近く、かつこちらはプラグイン機能もサポートされていたので、

あと標準機能でゴミ箱を空にするが使えたのも個人的に気に入ったところでした(macOSのAlfredでよく使っていた機能がempty trashなので)。

結論

そんなわけで、今はFlow Launcherを使っています。

プラグインも当初はC#Pythonでの開発でしたが、最近JavaScript/TypeScriptもサポートされたので、裾野が広がってくれるといいな。

デスクトップ上のファイルを掃除するFlow Launcherプラグインを作った

Flow Launcher用のプラグインを初めて作ってみました。

umi-uyura/Flow.Launcher.Plugin.DesktopCleanup

プラグインページにも掲載してもらえました。

f:id:umi-uyura:20220123223221p:plain

Flow Launcherとは

Flow LauncherはWindows用のアプリケーションランチャーです。

Macだと Alfred が有名でしょうか。

以前は Hain を使っていたのですが、いつの間にかリポジトリアーカイブ状態になっていて、開発が止まってしまっているようでした。

f:id:umi-uyura:20220123223239p:plain

そこで乗り換え先を探していくつかのランチャーアプリを試してみて、個人的に気に入ったので使ってみているのがFlow Launcherです。

Flow Launcher

wingetでインストールできます。

> winget install "Flow Launcher"

自分でプラグインを作ることができるものを探していて、Flow Launcherは.NET(C#) / Pythonで書くことができます。

※私が2,3ヶ月前に着手したときには上記2つがメインでしたが、最近になってJavaScript/TypeScriptでの開発方法もドキュメントに追加されました。

About Flow's TypeScript/JavaScript plugins

Desktop Cleanupプラグイン

今回作ったのは、デスクトップにあるファイルやフォルダを削除する、もしくはゴミ箱に移動するプラグインです。

私はデスクトップにはゴミ箱以外のファイル等を置かない派なのですが、wingetやChocolateyを使ってアプリケーションをインストールしたりアップデートをするたびにショートカットが作られてしまったりするので、それをサクッと削除したいときに使います。

f:id:umi-uyura:20220123223259g:plain

Flow Launcherを使っている方であれば、ランチャーに pm install desktop cleanup と入れて実行するか、もしくは設定画面のPlugin StoreからDesktop CleanupのInstallボタンを押すことでもインストールできます。

f:id:umi-uyura:20220123223325p:plain

dc clean で削除、 dc trash だとゴミ箱に移します。

ちなみにゴミ箱に入れた場合でも、Flow Launcherで Empty Recycle Bin を実行するとゴミ箱を空にできるので、いきなり削除するのが怖い人でも安心です。

今回のハマりどころ

Publicユーザーのデスクトップ

単純にデスクトップ上にあるファイル(ショートカット)を削除するだけなので大したことないと思っていたのですが、いざやってみたら削除されない、というかそもそもプログラムからも見えないファイルがあって、その解明に時間を使ってしまいました。

見えないと思っていたのは、実際には全てのユーザー向けにインストールされたアプリのショートカットでした。

これは実体としてはPublicというユーザーのデスクトップ上に存在しており、それが個々のユーザーのデスクトップ上にも表示されるというWindowsの仕組みでした。(たしかXPあたりのころはAll Usersという名前だった気がする)

インストーラですべてのユーザー向けにインストールした場合など、実際にはこのような仕組みになっていたんですね。

このため、自分のデスクトップ上では見えているのに、コマンドプロンプトなどでデスクトップフォルダの中を見た場合には(当然)存在していないということになります。

f:id:umi-uyura:20220123223343p:plain

当初、プログラム上から自分のデスクトップのパス( %USERPROFILE\Desktop )にあるファイルを削除するようにしていましたが、そうするとPublicユーザーのデスクトップ( %PUBLIC%\Desktop )にあるものは当然パスに含まれないために消えせん。

最初はなぜ見えないのかわからず、権限の問題?シンボリックリンクの種類?など見当違いの方向を調べていましたが、消せないショートカットのプロパティの場所に表示されているパスを見てようやく気づいた次第です。

f:id:umi-uyura:20220123223358p:plain

基本的にPCは一人でしか使わないですし、デスクトップに何か置かれたらすぐに削除するかどこかに移してしまうこともあって今まで気にしたことがありませんでしたが、今更ながらWindowsのマルチユーザーの仕組みの一端を知りました。

Windows 10でPython環境構築 (wingetとPythonランチャー)

基本的にはPython触るならWSL側にHomebrewとasdfで作った環境を使おうと思いますが、Windows側で何かをするときのために、Windows側にもPython環境を作ることにしました。

umi-uyura.hatenablog.com

まだ何もインストールしていないときの環境。

>where python
C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\python.exe

>python --version
Python

デフォルトで python.exe が存在していますが、バージョン情報を表示しようとしても python としか表示されません。

これを実行するとMicrosoft Storeが起動して、ストア版のPythonのページに飛びます。

そこからインストールすることもできますが、ストア版のPythonには制限もあるようなので、Python公式サイトで配布されるインストーラ版を使うことにしました。

参考)

Pythonをインストールする

公式サイトからダウンロードしても良いですが、wingetでもインストールできます。

> winget install -s winget -e --id Python.Python.3

refreshenv コマンドで環境変数を読み直すと、Python関連のパスが2つ追加されていました。

>refreshenv
Refreshing environment variables from registry for cmd.exe. Please wait...Finished..

>set | findstr /i python
Path=(中略)C:\Users\<user>\AppData\Local\Programs\Python\Python310\Scripts\;C:\Users\<user>\AppData\Local\Programs\Python\Python310\;(以降、略)

Pythonコマンドの実体を調べてみます。

>where python
C:\Users\<user>\AppData\Local\Programs\Python\Python310\python.exe
C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\python.exe

>where pip
C:\Users\<user>\AppData\Local\Programs\Python\Python310\Scripts\pip.exe

>where pip3
C:\Users\<user>\AppData\Local\Programs\Python\Python310\Scripts\pip3.exe

>where py
C:\Windows\py.exe

もともと存在していた python.exe に加えて、追加されたPATHの方にも python.exe が見つかりました。

また、複数のPythonのバージョンを切り替えて使えるPythonランチャー(py.exe)もインストールされていることを確認できました。

python でも py でも、バージョン情報が出力されることを確認。

>python --version
Python 3.10.1

>py --version
Python 3.10.1

参考)

PATHは必ずしも通っていなくて良いらしい。

確かに今後別のバージョンを追加したときに混乱しそうなので、いったん以下は環境変数から消して使ってみることにしました。

C:\Users\<user>\AppData\Local\Programs\Python\Python310\
C:\Users\<user>\AppData\Local\Programs\Python\Python310\Scripts\

※このあと3.9を追加インストールする際に、PATHを追加せずにインストールする方法を記載しています。

Pythonランチャー(py.exe)で複数バージョンを切り替えてみる

Pythonランチャーで別のバージョンを使いたい場合は、 py <version> と使いたいバージョンを指定して実行します。

>py <version> <script>      # 最新バージョンで実行
>py -3 <script>             # 3系の最新バージョンで実行
>py -3.9 <script>           # 3.9で実行

指定したバージョンがインストールされていない場合は、その旨表示されます。

>py -3.9 --version
Python 3.9 not found!
Installed Pythons found by py Launcher for Windows
 -3.10-64 *

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

試しに -3.9 を指定してみると上記のようなメッセージが表示されましたので、追加で3.9をインストールしてみます。

wingetでインストールできる過去のバージョンは winget show --versions <query> で取得できます。

>winget show --versions --id Python.Python.3
見つかりました Python 3 [Python.Python.3]
バージョン
-----------
3.10.1150.0
3.10.150.0
3.9.7150.0
3.9.6150.0
3.9.5150.0
...

3.9系の最新である 3.9.7150.0 をインストールするため、wingetに --version オプションを付けてバージョンを指定して実行します。

>winget install -s winget -e --id Python.Python.3 --version 3.9.7150.0 --override PrependPath=0

また --override PrependPath=0 を付けることで、環境変数PATHへの追加されずにインストールすることができます。

このときインストーラの画面が開くので、 Add Python 3.9 to PATH のチェックが外れていることを確認して、「Install Now」を選べばOKでした。

f:id:umi-uyura:20211214233022p:plain

インストール後に python の所在を確認してみます。

>where python
C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\python.exe

>py --version
Python 3.10.1

>py -3.9 --version
Python 3.9.7

PATHは追加されていませんが、 py -3.9 で3.9版のバージョンが表示されました。

現在の環境にインストールされているバージョンを一覧表示するには --list もしくは --list-paths を使います。

>py --list
Installed Pythons found by py Launcher for Windows
 -3.10-64 *
 -3.9-64

>py --list-paths
Installed Pythons found by py Launcher for Windows
 -3.10-64       C:\Users\<user>\AppData\Local\Programs\Python\Python310\python.exe *
 -3.9-64        C:\Users\<user>\AppData\Local\Programs\Python\Python39\python.exe

* が付いているバージョンがデフォルトで使われるもので、これは設定で変更することができます。

参考)

Pythonランチャー+venv

Pythonランチャーでvenvが使えるかを確認します。

>py --version
Python 3.10.1

>py -3.9 -m venv .venv

デフォルトが 3.10 の状態で、 3.9 を指定してvenv環境を作ります。

>.venv\Scripts\activate

(.venv) >py --version
Python 3.9.7

activate すると、何も指定しないで実行した py が返すバージョンが 3.9 になりました。

(.venv) >where python
C:\Users\<user>\workspace\python\pyexe-test\.venv\Scripts\python.exe
C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\python.exe

作成したvenv環境の python が優先されるようになっていました。

(.venv) >py --list-paths
Installed Pythons found by py Launcher for Windows
 (venv)         C:\Users\<user>\workspace\python\pyexe-test\.venv\Scripts\python.exe *
 -3.10-64       C:\Users\<user>\AppData\Local\Programs\Python\Python310\python.exe
 -3.9-64        C:\Users\<user>\AppData\Local\Programs\Python\Python39\python.exe

py --list-paths してみても、venv環境が追加されていました。


最新版以外を使う場合は、都度使うバージョンを指定する必要がありますが、いちいち切り替えなくて済むという点では、pyenv方式よりPythonランチャーの方が使い勝手は良いのかも。

とりあえず、Windows側でPython使うときはPythonランチャーを意識して使ってみます。

参考