[AI基礎解説]PATHと環境変数の超入門(Mac / Windows / WSL)— “コマンドが見つからない”を根絶する
ねらい:command not found や “別のPythonが動く” を根本から防ぎ、どのPCでも同じ挙動を出す。
対象:AI/WEB開発の初〜中級者/チーム開発者。
ゴール:PATHと環境変数を安全に追加・確認・共有できる。
TL;DR(まずはこれだけ)
PATHは“左から順に”検索される(左が勝つ)。追加は先頭にprependが基本。
設定ファイルは場所を間違えない(Macは .zprofile と .zshrc、WindowsはUser PATHが安全)。
現セッションで動いても永続しないことがある(Windowsのsetxは新しいシェルから有効)。
機密は .env に分離、リポジトリには**.env.exampleのみ**を置く。
1) まず“今”の状態を確認する
共通(どのOSでも)
# どのPython/どのpipが使われているか
python -c "import sys;print(sys.executable)"
python -m pip --version
# PATHを1行ずつ見る(macOS/Linux/WSL)
echo "$PATH" | tr ':' '\n' | nl
Windows(PowerShell)
# どのpythonか
(Get-Command python).Source
# PATHを1行ずつ
$env:PATH -split ';' | % {$_} | % {$i=0}{++$i; "$i`t$_"}
原則:失敗の8割は“想定外の実行器”が先頭にあること。順序を可視化してから直す。
2) macOS(zsh)の正しい置き場所と書き方
どこに書く?
~/.zprofile:ログイン時に1回だけ読ませたいもの(PATHの初期化)。
~/.zshrc:毎回の対話シェルで読みたいもの(エイリアス、関数、補完など)。
HomebrewはIntel/M1でパスが違うので分岐する。
推奨スニペット(貼るだけ)
# ~/.zprofile ← PATHの初期化はこっち
# Homebrew
if [[ -d /opt/homebrew/bin ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)" # Apple Silicon
elif [[ -d /usr/local/bin ]]; then
export PATH="/usr/local/bin:$PATH" # Intel
fi
# よく使うローカルbinを先頭に(重複追加を防ぐ)
prepend_path () { case ":$PATH:" in *":$1:"*) ;; *) export PATH="$1:$PATH";; esac }
prepend_path "$HOME/.local/bin"
prepend_path "$HOME/.poetry/bin"
# ~/.zshrc ← 対話設定はこちら
# 補完やエイリアスなど
autoload -U compinit && compinit
alias ll='ls -alF'
# PATHの見える化(任意)
path() { echo "$PATH" | tr ':' '\n' | nl; }
反映:新しいターミナルを開くか、exec $SHELL -l(ログインとして再起動)。
アンチパターン:.zshrcと.zprofileの両方でPATHを上書き → 順序が壊れる。
3) Windowsの基本(User PATHを安全に)
スコープの違い
Process(現在のシェルだけ)
User(自分のアカウント全体)←まずはこれ
System(全ユーザ)←管理者用途。失敗時の影響が大きいので避ける
一時的に試す(現セッションのみ)
# 先頭に追加(再起動不要・セッション限定)
$env:Path = "C:\Users\<you>\AppData\Local\Programs\Python\Python39\Scripts;" + $env:Path
永続化(ユーザPATHへ・安全版)
# 既存のUser PATHを取得
$u = [Environment]::GetEnvironmentVariable('Path','User')
# 追記(重複チェックは必要に応じて)
$new = "C:\Tools\bin;$u"
[Environment]::SetEnvironmentVariable('Path',$new,'User')
反映:新しいPowerShellを開く(既存セッションには効かない)。
注意:setx は簡単だが長いPATHを切り詰めることがある。上の .NET API 方式が安全。
スペースを含むパス:"C:\Program Files\Git\cmd" のように必ず二重引用符で扱う。
4) WSL2(Windows上のLinux)でのコツ
プロジェクトはLinux側に置く:\\wsl$\Ubuntu\home\<you>\project(/mnt/c/... はI/Oが遅い)。
Windows PATHの混入を制御(再現性重視):
/etc/wsl.conf(ディストロ内)に追記 → wsl --shutdown → 再起動。
[interop]
appendWindowsPath=false
[automount]
options="metadata,umask=22,fmask=11" # 権限の整合を取りやすくする
DNSや時計ズレでネット/証明書が失敗することがある → wsl --status / wsl --update で更新、Windows側の時刻同期。
5) 環境変数の扱い(.env / 12-Factor)
原則
秘密はコードに直書きしない。.env に置く。
リポジトリには .env をコミットしない、代わりに .env.example を置く。
本番はOSの環境変数やシークレットマネージャで注入。
最小雛形
# .env (コミットしない)
DATABASE_URL=postgres://user:pass@localhost:5432/app
SECRET_KEY=change-me
# .env.example (コミットする)
DATABASE_URL=postgres://user:pass@localhost:5432/app
SECRET_KEY=__FILL_THIS__
Python(ローカル実行):python-dotenv で読み込む。
# app.py
from dotenv import load_dotenv; load_dotenv()
# os.environ['SECRET_KEY'] が使える
Docker Compose:composeファイルと同じディレクトリの .env が自動読込。実際に反映された値は docker compose config で確認。
6) “順序”と“競合”の落とし穴(典型パターン)
別のPythonが先頭にいる
例:Xcode付属のPython、旧Anaconda、古い/usr/local/bin/python など
対処:PATH順序を入れ替えるか、実行は常に python -m で。
同名コマンドの多重インストール
例:pip が3つある → 何が先か which -a pip / Get-Command pip -All で洗い出す
対処:python -m pip 原則で回避。
改行コード(CRLF)でスクリプトが動かない(WSL/mac)
対処:.gitattributes で eol=lf、既存は dos2unix。
設定を上書き合っている
例:.zprofile と .zshrc、複数のsetx、複数の.env
対処:“どこに何を書くか”を決めてドキュメント化。被らせない。
7) チームで共有する“安全テンプレ”
macOS(貼るだけ)
# ~/.zprofile
if [[ -d /opt/homebrew/bin ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -d /usr/local/bin ]]; then
export PATH="/usr/local/bin:$PATH"
fi
prepend_path () { case ":$PATH:" in *":$1:"*) ;; *) export PATH="$1:$PATH";; esac }
prepend_path "$HOME/.local/bin"
prepend_path "$HOME/.poetry/bin"
Windows(PowerShellスクリプト)
# add-path.ps1
param([string]$NewPath)
$u = [Environment]::GetEnvironmentVariable('Path','User')
if ($u -notlike "*$NewPath*") {
[Environment]::SetEnvironmentVariable('Path', "$NewPath;$u", 'User')
"Added to User PATH: $NewPath`nRestart the terminal."
} else { "Already present: $NewPath" }
.gitattributes(改行の地雷排除)
*.sh text eol=lf
*.py text eol=lf
Dockerfile text eol=lf
8) 診断の順番(困ったらこれ)
実行器の特定:sys.executable / Get-Command python
PATHの並びを見る:tr ':' '\n' / -split ';'
仮想環境の有効化:source .venv/bin/activate / .\.venv\Scripts\activate
python -m原則で再実行:python -m pip, python -m pytest
設定ファイルを最小化:.zprofile だけで再現 → 問題切り分け
WSLなら置き場所を確認:Linux側か?metadata有効か?
新しいシェルで確認:Windowsは特に再起動必須
まとめ(今日からの運用)
PATHは先頭勝ち。追加はprepend、重複防止の関数で。
設定の責務分離:macOSは.zprofile(PATH)と.zshrc(対話)、WindowsはUser PATH中心。
機密は .env、リポジトリは**.env.example**で共有。
迷ったら**実行器の可視化→PATHの順序→python -m**で切り分け。
