Keypirinha の Obsidian プラグインを Codex で開発中に遭遇した問題の解決ログです
概要
Obsidian CLI(daily:append)が、Windows 環境において以下のような挙動差を示した
-
obsidian daily:append ...は PowerShell / Cmd から正常動作 - Python 3.11.9 の
subprocess.run(["obsidian", ...])では失敗 -
subprocess.run(["obsidian.com", ...])では正常動作 -
cmd /c obsidian ...では正常動作
この差異の原因を切り分けるため、Process Monitor によるプロセス生成追跡を行った
発端
最初の問題は Keypirinha プラグイン内で発生
- Keypirinha から Obsidian CLI を呼び出すも処理が失敗
-
obsidian daily:appendが実行されない - エラーコードや出力がなく原因が不明
検証を進めると、同じ問題は Python 単体でも再現し、Keypirinha 固有の問題ではない事がわかった
再現方法
予め Obsidian CLI は設定から有効にしておく
成功ケース
obsidian daily:append vault=Memos content=test
python -c "import subprocess; r=subprocess.run(['obsidian.com','daily:append','vault=Memos','content=test'], capture_output=True, text=True); print(r.returncode); print(r.stdout); print(r.stderr)"
obsidian.com としていると成功する
失敗ケース
python -c "import subprocess; r=subprocess.run(['obsidian','daily:append','vault=Memos','content=test'], capture_output=True, text=True); print(r.returncode); print(r.stdout); print(r.stderr)"
obsidian だけだと失敗する
- returncode = 4294967295
- stdout / stderr = 空
補足
回避策
明示的に cmd から呼ぶようにすると成功する
# keypirinhaから実行
subprocess.run("obsidian daily:append ...", shell=True)
# keypirinhaから実行
subprocess.run(["cmd", "/c", "obsidian", "daily:append", ...])
version は成功する
# keypirinhaから実行
subprocess.run(['obsidian','version'])
環境情報
環境を確認した
where obsidian
-> 〜\AppData\Local\Obsidian\obsidian.exe
-> 〜\AppData\Local\Obsidian\Obsidian.com
-
.comと.exeの両方が存在する構成だった
exe は GUI ツールで、com が cli 用のツールであると思われる(未確認)
python -c "import os; print(os.environ['PATHEXT'])"
-> .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.RB;.RBW;.CPL
Windows が拡張子なしのコマンドを実行するときに検索対象に COM は存在
COM が EXE よりも優先される設定だった
調査手順
1. PATH 解決確認
import shutil
shutil.which("obsidian")
結果:
〜\AppData\Local\Obsidian\obsidian.COM
問題なし
2. subprocess コマンド展開確認
import subprocess
subprocess.list2cmdline([...])
問題なし
3. Process Monitor による解析
プロセス モニター(procmon.exe)を使用し、プロセス生成を追跡
フィルタ:
- Process Name = python.exe
- Operation = Process Create
観測結果
python.exe
→ Process Create
Image: 〜\AppData\Local\Obsidian\obsidian.exe
Command line:
obsidian daily:append vault=Memos content=test
exe 呼んどる!!
結論
Python の以下の呼び出し:
subprocess.run(["obsidian", ...])
は内部的に Obsidian.exe を起動している ことが分かった
一方で、正常動作するケースは Obsidian.com を呼んでいた
原因
本現象は以下の構造によるものと整理できる
1. Windows の同名実行ファイル共存
-
Obsidian.exe(GUI アプリ) -
Obsidian.com(CLI)
2. subprocess.run の名前解決
"obsidian" 指定時:
-
.exeが優先されて実行される- → CLI 用途の
.comが選ばれない
- → CLI 用途の
3. Cmd / PowerShell との違い
- Cmd / PowerShell → PATHEXT 順で解決
- Python subprocess → 別経路で
.exe優先で解決
対応
subprocess.run([
"obsidian.com",
"daily:append",
...
])
補足
-
.comはコンソールアプリのため一瞬ウィンドウが出た -
subprocess.STARTUPINFOを追加することで非表示化できた -
obsidian versionは exe でも結果が返ってきた- 非同期処理のような挙動ではあった
まとめ
Obsidian CLI(daily:append)が、Windows 環境において、PowerShell / cmd から呼んだ場合と subprocess.run() で呼んだ場合で挙動差があったのは
「同名の EXE/COM 共存 + PS/Cmd と subprocess の名前解決順の違い」
が原因だった