英語613639 views
数学講師2886227 views
世界の国564520 views
高校物理160203 views
中学英語811710 views
中学社会668760 views
高校国語788336 views
高校化学2924392 views
LaTeX962153 views
Computer368106 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

相対パスの罠:カレントディレクトリが変わると壊れるコード

相対パスを使ったコードは、カレントディレクトリ(作業ディレクトリ)が変わると壊れる。これはよくあるバグの原因だ。

問題の例

# ❌ カレントディレクトリに依存するコード
# script.py
with open('config.json') as f:
    config = json.load(f)

このスクリプトは、スクリプトと同じディレクトリから実行すれば動く。

cd /home/user/myapp
python script.py  # 動く

しかし、別のディレクトリから実行すると動かない。

cd /home/user
python myapp/script.py  # FileNotFoundError

config.json/home/user/config.json を探しに行くが、実際には /home/user/myapp/config.json にあるからだ。

なぜカレントディレクトリが変わるのか

カレントディレクトリが変わる状況は多い。

ユーザーが異なるディレクトリからスクリプトを実行する
cron やサービスとして実行される(カレントディレクトリが / や /root になる)
IDE やテストフレームワークがプロジェクトルートから実行する
コード内で os.chdir() を呼んでいる

__file__ を使った解決方法

スクリプトの場所を基準にパスを解決すれば、どこから実行しても動く。

# ✅ スクリプトの場所を基準にする
from pathlib import Path

script_dir = Path(__file__).resolve().parent
config_path = script_dir / 'config.json'

with open(config_path) as f:
    config = json.load(f)

__file__ はスクリプト自身のパスを持つ特殊変数だ。resolve() で絶対パスに変換し、parent でディレクトリ部分を取得する。

os.path を使う場合

pathlib を使わない場合は os.path で同じことができる。

import os

script_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(script_dir, 'config.json')

パッケージ内のリソースファイル

パッケージ内のリソースファイルにアクセスする場合は importlib.resources を使う方が確実だ。

# Python 3.9 以降
from importlib.resources import files

config_text = files('mypackage').joinpath('config.json').read_text()

__file__ はパッケージが zip 化されている場合などに使えないことがあるが、importlib.resources はそのような状況でも動作する。

os.chdir() の危険性

コード内で os.chdir() を使うと、以降のすべての相対パスに影響する。

# ❌ 危険なコード
os.chdir('/tmp')
# この後のすべての相対パスが /tmp 基準になる
with open('data.txt') as f:  # /tmp/data.txt を開こうとする
    pass

どうしても chdir() が必要な場合は、コンテキストマネージャで元に戻す。

import os
from contextlib import contextmanager

@contextmanager
def working_directory(path):
    old = os.getcwd()
    try:
        os.chdir(path)
        yield
    finally:
        os.chdir(old)

# 使用例
with working_directory('/tmp'):
    # ここだけカレントディレクトリが /tmp
    pass
# 元のディレクトリに戻る

ベストプラクティス

相対パスは極力使わず、__file__ 基準の絶対パスを使う
os.chdir() は避けるか、必ず元に戻す
設定ファイルのパスは環境変数や引数で渡せるようにする