AI自動化

Python 環境ズレ デバッグチェックリストと再発防止コマンド集

Python 環境ズレ デバッグチェックリストと再発防止コマンド集

Python 環境ズレ デバッグチェックリストと再発防止コマンド集

noteの自動投稿スクリプトが「完走しているのに公開されない」という状態に陥ったことがある。エラーはない。ログも綺麗。でも結果がおかしい。

原因を探るのに40分かかった。答えは (略) 一発で出た。

この記事でわかること:
– Pythonがどの環境で動いているか一発で確認する方法
– 環境ズレが起きる原因パターン4種
– launchd/cronで実行するスクリプト固有の落とし穴
– 再発防止のためのデバッグチェックリスト(コピペ可)


どのPythonが動いているか?環境別の特徴比較

環境 パス例 よくある罠
システムPython /usr/b​in/python3 macOS標準、パッケージ追加不可
Homebrew Python /opt/homebrew/b​in/python3 brew upgrade後にバージョンが上がる
pyenv ~/.pyenv/shims/python3 PYENV_VERSION設定ミスで別バージョンが動く
venv /path/to/venv/b​in/python3 activate忘れ・別シェルで実行すると無効
Conda /opt/miniconda3/envs/xxx/b​in/python base環境で動いて気づかない

問題は「動く」という点にある。エラーが出ないから気づけない。古い環境・古いライブラリで処理が進み、意図しない挙動を返す。


40分溶かした実体験——何が起きていたか

スクリプトはnoteの自動投稿処理。Playwright + Chromiumで動いている。

完走する。ログも正常終了。でも noteのダッシュボードを確認すると「下書き」のまま。公開されていない。

ログを掘り始めた。(略) のURL検出ロジックを疑った。(略) への直接遷移を実装したはずが、古い処理フローが動いていた形跡がある。(略) で座標クリックに切り替えたコードも反映されていない。

「あれ、コードを修正したはずでは?」——ここで気づいた。

(コード例は元記事を参照)

想定は (略) だった。修正を入れたコードは新しいvenvに配置済み。でも launchd の plist は古いPythonパスを参照したままだった。それだけの話。

「それだけ」に40分かかった。


環境ズレが起きる4つの原因パターン

パターン1: launchd/cron がシェル設定を読まない

(略)(略) に書いた (略)(略) も、launchdから実行されるスクリプトには効かない。絶対パスで Python バイナリを指定しないといけない。

(コード例は元記事を参照)

私はこれを知っていたのに、plistの更新を忘れた。

パターン2: venv を activate したのに別シェルで実行した

ターミナルのタブAで (略)、タブBで (略)。タブBにはactivateが伝播していない。特にマルチタブ作業時にやりがちで、エラーが出ないから気づかない。

パターン3: Homebrew アップデート後にパスが変わる

(略) を実行すると Python のバージョンが上がる。pyenvのシムが古いバージョンを参照し続けるケースがある。

(コード例は元記事を参照)

アップデート後は (略) を確認する習慣が必要だった。

パターン4: どの pip でインストールしたか不明

「pip install したはずなのに ModuleNotFoundError」は大体これ。(略)(略) が一致していないと、違う環境にインストールしていることになる。

(コード例は元記事を参照)


コピペで使えるデバッグチェックリスト

「なんかおかしい」と思ったらこれを上から流す。

(コード例は元記事を参照)

スクリプトの冒頭に仕込んでおくと、ログで即確認できる:

(コード例は元記事を参照)

launchd経由のスクリプトには必ずこれを入れるようにした。ログファイルを見ればどの環境で動いたか一発でわかる。


launchd 固有の落とし穴——plist 更新忘れ

今回の事故の根本はここだった。venvを作り直したとき、plistを更新しなかった。

plistを変更したらリロードが必要:

(コード例は元記事を参照)

「unload → load」を忘れると、古いplistが有効なまま動き続ける。変更が反映されていないのに反映されたと思ってしまう。


よくある質問

venv を activate したのに効いていないのはなぜ?

(略) はそのシェルセッション内にのみ有効。launchd・cron・別プロセスからの呼び出しには伝播しない。解決策は venv内の Python バイナリを絶対パスで指定すること。(略) で直接実行するか、shebang行に書く。

(略) したのに (略) でエラーが出る

(略)(略) の結果ディレクトリが揃っているか確認。食い違っていれば別環境にインストールしている。(略) で実行すると、今の (略) に紐づく pip が使われるので確実。

pyenv と venv はどちらを使えばいいか?

用途が違う。pyenvは「Pythonのバージョン」を切り替えるもの、venvは「同じバージョン内でパッケージを分離」するもの。私はpyenvでバージョンを固定したうえで、プロジェクト毎にvenvを切る構成にしている。launchdから実行するスクリプトはvenv内のバイナリを直接指定。

スクリプトを修正したのに古い挙動のまま

「どの環境のコードを実行しているか」と「どの環境に修正を加えたか」がズレている可能性がある。(略) でPythonのパスを確認し、そのパスの (略) に最新コードが入っているか確認する。launchd plist が古いパスを参照していないかも確認。

Homebrew の Python と pyenv が混在して混乱している

(略) で警告を確認。PATH の順番が問題のことが多い。(略)(略) を先頭に置くと pyenv が優先される。ただし launchd は (略) を読まないので、plist には絶対パスを書く。


まとめ

  • 「動いているのに結果がおかしい」ときは (略)(略) を最初に疑う
  • launchd/cronは (略) を読まない。絶対パス指定が必須で、plist変更後は必ずリロード
  • venvのパスを変えたら plist も同時に更新する。片方だけ変えると今回の事故が再現する
  • スクリプト冒頭に (略) ログを入れると、ログファイルで環境を即確認できる
  • (略) を使うと、今の python3 に確実にインストールできる
  • pip と python3 の (略) 結果ディレクトリを揃えるのが基本

40分は取り戻せないけど、チェックリストは残った。✨


この記事を読んだあなたに:
– launchd で Python スクリプトを自動実行する設定方法 /launchd-python-autorun
– pyenv + venv の環境構築を30分で終わらせる手順 /pyenv-venv-setup
– Python 自動化スクリプトのエラーログを Discord に飛ばす実装 /python-discord-error-log


(コード例は元記事を参照)