PythonのFileNotFoundErrorを直す方法 パスと作業フォルダの確認
ファイルはあるのにPythonでFileNotFoundErrorが出る原因を、相対パスと作業フォルダから確認。pathlibと__file__を使う直し方を解説します。
「同じフォルダに置いたのに、ファイルがないと言われる」。PythonでFileNotFoundErrorが出たら、まずPythonが探している場所を表示してみてください。
ファイルがPCに存在していても、指定した場所にあるとは限りません。今回はPython 3で、読み取り先のずれを調べ、意図したファイルを開くまでを順番に見ていきます。open()とwithの基本はファイル読み書きの入門で確認できます。
FileNotFoundErrorとPermissionErrorは別の問題
FileNotFoundError: [Errno 2] No such file or directory: 'data.txt'
このエラーは、指定されたファイルやフォルダが見つからないことを知らせています。末尾の'data.txt'は、開こうとした名前の手掛かりです。必要なアクセス権がない場合のPermissionErrorとは区別します。Python公式の例外一覧
「開けないから管理者として実行する」と決める前に、エラー名を確かめましょう。場所の指定が間違っているなら、権限を変えても目的のファイルは見つかりません。
1. 相対パスが何を基準にするか確認する
次の2つを同じフォルダへ置いたとします。
study/
├─ main.py
└─ data.txt
main.pyの内容は、次のとおりです。
with open("data.txt", "r", encoding="utf-8") as file:
print(file.read(), end="")
"data.txt"のように、完全な場所を指定しない書き方を相対パスと呼びます。ファイルまでの道順だと思えば大丈夫です。通常、基準はPythonファイル自身の場所ではなく、現在の作業フォルダです。openの相対パスの仕様
例えば作業フォルダがstudyなら、その中のdata.txtを探します。作業フォルダが1つ上なら、そちらのdata.txtを探します。同じコードでも、実行方法によって結果が変わる理由の一つです。
2. 現在地と読み取り先を表示する
ファイルを開く前に、次を加えて確認します。
from pathlib import Path
path = Path("data.txt")
print("作業フォルダ:", Path.cwd())
print("探している場所:", path.resolve())
print("ファイルとして見つかる:", path.is_file())
pathlibは、Pythonに標準で付いている、ファイルやフォルダの場所を扱う道具です。Path.cwd()は現在地、resolve()は完全な場所を調べるのに使えます。is_file()は通常のファイルとして見つかるかの確認です。pathlib公式資料
表示された場所と、エクスプローラーなどで確認した実際の場所を比べます。Falseでも、それだけで原因を断定せず、フォルダ名とファイル名を一つずつ確認してください。
ここでは存在確認に使っていますが、「確認後には絶対に開ける」という保証ではありません。確認と読み込みの間に移動や削除が起こる場合もあるため、実際の読み込み時の対応は別に考えます。
3. 目的に合わせて基準を決める
作業フォルダを基準に読む
構成が次の場合を考えます。
study/
├─ main.py
└─ data/
└─ message.txt
作業フォルダがstudyなら、dataも含めます。
from pathlib import Path
path = Path("data") / "message.txt"
with path.open("r", encoding="utf-8") as file:
print(file.read(), end="")
Path同士をつなぐ/は、ここでは割り算ではなく、下のフォルダやファイルを指定する書き方です。
main.pyの場所を基準に読む
プログラムに付属するデータを、main.pyの隣から読みたいなら、こちらの形にできます。通常の.pyファイルとして保存して実行してください。
from pathlib import Path
base_dir = Path(__file__).resolve().parent
path = base_dir / "data" / "message.txt"
with path.open("r", encoding="utf-8") as file:
print(file.read(), end="")
__file__は、そのPythonファイルの場所を表します。.parentで親フォルダを取得し、そこへdata/message.txtをつなげています。対話型画面やノートブックなどでは、__file__が使えない場合があります。Pythonのモジュール属性
自分のPCだけの絶対パスを埋め込むより、「プログラムの隣」という意図を保ちやすい書き方です。
名前と書き込みモードの落とし穴
場所が合っていたら、つづり、拡張子、大文字・小文字を見比べます。Windowsで拡張子を隠していると、data.txtのつもりがdata.txt.txtになっていることもあります。実際の名前を表示して比べてください。
読み込みの"r"を"w"へ変えてエラーを消すのは避けましょう。"w"は書き込み用で、同名のファイルがあると内容を消します。読みたいものを作り直す操作ではありません。
また、"w"でも親フォルダは自動作成されません。result/output.txtへ書くなら、resultがあるかを別に確認します。エラー対処では、読みたいのか、保存したいのかを先に決めると混乱しにくくなります。
練習:どこから実行しても付属ファイルを読む
次の構成で、main.pyと同じ階層のdataからscore.txtを読みたいものとします。作業フォルダに左右されない形へ直してください。
study/
├─ main.py
└─ data/
└─ score.txt
練習用にscore.txtを作り、80と書いて保存しておきます。
模範解答
from pathlib import Path
base_dir = Path(__file__).resolve().parent
path = base_dir / "data" / "score.txt"
try:
with path.open("r", encoding="utf-8") as file:
text = file.read()
except FileNotFoundError:
print("指定したファイルが見つかりません:", path)
else:
print(text, end="")
解説
基準はmain.pyの親フォルダです。別のフォルダからこのファイルを起動しても、付属のdata/score.txtを指定できます。用意した内容が80なら、それを表示します。
exceptはファイルがなくなった場合の案内です。読み取り先の間違いを直す機能ではありません。案内が出たら、表示された場所と実際の配置を比べます。失敗を隠すだけで終えず、どこを探したかまで見えるようにすると調べやすくなります。
次はNameErrorで名前が見つからない場合や、エラー表示を読む基本も確認してみてください。