1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Windows Python subprocess で Obsidian CLI の実行が失敗する

1
Posted at

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 が選ばれない

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 の名前解決順の違い」

が原因だった

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?