Python FileNotFoundError(ファイル未発見エラー)の原因と解決法|ファイル操作完全マスター

フリーランスボード

20万件以上の案件から、副業に最適なリモート・週3〜の案件を一括検索できるプラットフォーム。プロフィール登録でAIスカウトが自動的にマッチング案件を提案。市場統計や単価相場、エージェントの口コミも無料で閲覧可能なため、本業を続けながら効率的に高単価の副業案件を探せます。フリーランスボード

ITプロパートナーズ

週2〜3日から働ける柔軟な案件が業界トップクラスの豊富さを誇るフリーランスエージェント。エンド直契約のため高単価で、週3日稼働でも十分な報酬を得られます。リモートや時間フレキシブルな案件も多数。スタートアップ・ベンチャー中心で、トレンド技術を使った魅力的な案件が揃っています。専属エージェントが案件紹介から契約交渉までサポート。利用企業2,000社以上の実績。ITプロパートナーズ

Midworks 10,000件以上の案件を保有し、週3日〜・フルリモートなど柔軟な働き方に対応。高単価案件が豊富で、報酬保障制度(60%)や保険料負担(50%)など正社員並みの手厚い福利厚生が特徴。通勤交通費(月3万円)、スキルアップ費用(月1万円)の支給に加え、リロクラブ・freeeが無料利用可能。非公開案件80%以上、支払いサイト20日で安心して稼働できます。Midworks

Python開発でファイル操作を行う際に頻出する「FileNotFoundError(ファイル未発見エラー)」について、原因から実践的な解決法まで詳しく解説します。安全なファイル操作プログラミングの技術を身につけましょう。

FileNotFoundErrorとは

FileNotFoundErrorは、存在しないファイルやディレクトリにアクセスしようとした際に発生するエラーです。ファイルの読み込み、書き込み、削除などの操作で、指定されたパスにファイルが見つからない場合に発生します。

# FileNotFoundError例:存在しないファイルを開こうとする
with open("存在しないファイル.txt", "r") as file:
    content = file.read()
# FileNotFoundError: [Errno 2] No such file or directory: '存在しないファイル.txt'

FileNotFoundErrorが発生する主なパターン

1. 基本的なファイル読み込みエラー

最も基本的なFileNotFoundErrorの原因です。

# 間違い:存在確認なしでファイルを開く
filename = "data.txt"
with open(filename, "r") as file:
    content = file.read()
# FileNotFoundError(ファイルが存在しない場合)

# 正解:事前に存在確認
import os

filename = "data.txt"
if os.path.exists(filename):
    with open(filename, "r") as file:
        content = file.read()
        print("ファイルを読み込みました")
else:
    print(f"ファイル '{filename}' が見つかりません")

2. 相対パスと絶対パスの問題

パスの指定方法によってファイルが見つからない場合があります。

# 間違い:実行場所に依存する相対パス
with open("data/config.txt", "r") as file:
    config = file.read()
# 実行ディレクトリによってはFileNotFoundError

# 正解:絶対パスまたはスクリプト基準の相対パス
import os

# スクリプトファイルの場所を基準にしたパス
script_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(script_dir, "data", "config.txt")

if os.path.exists(config_path):
    with open(config_path, "r") as file:
        config = file.read()
else:
    print(f"設定ファイルが見つかりません: {config_path}")

3. ディレクトリ作成時のパスエラー

存在しないディレクトリ内にファイルを作成しようとした場合に発生します。

# 間違い:存在しないディレクトリにファイル作成
output_path = "output/results/data.txt"
with open(output_path, "w") as file:
    file.write("結果データ")
# FileNotFoundError(outputディレクトリが存在しない場合)

# 正解:ディレクトリを事前に作成
import os

output_path = "output/results/data.txt"
output_dir = os.path.dirname(output_path)

# ディレクトリが存在しない場合は作成
os.makedirs(output_dir, exist_ok=True)

with open(output_path, "w") as file:
    file.write("結果データ")
    print(f"ファイルを作成しました: {output_path}")

4. ファイル削除時のエラー

存在しないファイルを削除しようとした場合に発生します。

import os

# 間違い:存在確認なしでファイルを削除
filename = "temp.txt"
os.remove(filename)
# FileNotFoundError(ファイルが存在しない場合)

# 正解:安全なファイル削除
def safe_remove_file(filename):
    try:
        os.remove(filename)
        print(f"ファイルを削除しました: {filename}")
        return True
    except FileNotFoundError:
        print(f"削除対象のファイルが見つかりません: {filename}")
        return False
    except PermissionError:
        print(f"ファイルの削除権限がありません: {filename}")
        return False

safe_remove_file("temp.txt")

5. CSVやJSON ファイルの読み込みエラー

データファイルの読み込み時によく発生します。

import csv
import json

# 間違い:存在確認なしでCSVファイルを読み込み
with open("data.csv", "r") as csvfile:
    reader = csv.reader(csvfile)
    for row in reader:
        print(row)
# FileNotFoundError

# 正解:安全なCSVファイル読み込み
def safe_read_csv(filename):
    try:
        with open(filename, "r", encoding="utf-8") as csvfile:
            reader = csv.reader(csvfile)
            data = list(reader)
            return data, None
    except FileNotFoundError:
        return None, f"CSVファイルが見つかりません: {filename}"
    except Exception as e:
        return None, f"CSVファイルの読み込みエラー: {e}"

data, error = safe_read_csv("data.csv")
if error:
    print(error)
else:
    print("CSVデータを読み込みました")

6. 画像・メディアファイルの処理エラー

画像やメディアファイルの処理でもよく発生します。

# 間違い:存在確認なしで画像ファイルを処理
from PIL import Image

img = Image.open("photo.jpg")
# FileNotFoundError

# 正解:安全な画像ファイル処理
def safe_open_image(filename):
    try:
        img = Image.open(filename)
        return img, None
    except FileNotFoundError:
        return None, f"画像ファイルが見つかりません: {filename}"
    except Exception as e:
        return None, f"画像ファイルの処理エラー: {e}"

image, error = safe_open_image("photo.jpg")
if error:
    print(error)
else:
    print(f"画像サイズ: {image.size}")

FileNotFoundErrorの対処法

1. pathlib モジュールの活用

from pathlib import Path

def safe_file_operations(filename):
    """pathlibを使った安全なファイル操作"""
    file_path = Path(filename)
    
    # ファイルの存在確認
    if file_path.exists():
        print(f"ファイルが存在します: {file_path}")
        
        # ファイル情報の取得
        if file_path.is_file():
            print(f"ファイルサイズ: {file_path.stat().st_size} bytes")
            print(f"最終更新: {file_path.stat().st_mtime}")
            
            # ファイルの読み込み
            try:
                content = file_path.read_text(encoding="utf-8")
                return content[:100] + "..." if len(content) > 100 else content
            except Exception as e:
                return f"読み込みエラー: {e}"
        else:
            return "指定されたパスはファイルではありません"
    else:
        return f"ファイルが見つかりません: {file_path}"

# 使用例
result = safe_file_operations("test.txt")
print(result)

2. try-except文での包括的な例外処理

def robust_file_reader(filename, encoding="utf-8"):
    """堅牢なファイル読み込み関数"""
    try:
        with open(filename, "r", encoding=encoding) as file:
            content = file.read()
            return {
                "success": True,
                "content": content,
                "error": None
            }
    except FileNotFoundError:
        return {
            "success": False,
            "content": None,
            "error": f"ファイルが見つかりません: {filename}"
        }
    except PermissionError:
        return {
            "success": False,
            "content": None,
            "error": f"ファイルの読み込み権限がありません: {filename}"
        }
    except UnicodeDecodeError:
        return {
            "success": False,
            "content": None,
            "error": f"文字エンコーディングエラー({encoding}): {filename}"
        }
    except Exception as e:
        return {
            "success": False,
            "content": None,
            "error": f"予期しないエラー: {e}"
        }

# 使用例
result = robust_file_reader("config.txt")
if result["success"]:
    print("ファイル内容:", result["content"][:50])
else:
    print("エラー:", result["error"])

3. デフォルトファイルの作成

def ensure_config_file(config_path, default_config):
    """設定ファイルの存在を保証し、なければデフォルトを作成"""
    import json
    from pathlib import Path
    
    config_file = Path(config_path)
    
    # ディレクトリが存在しない場合は作成
    config_file.parent.mkdir(parents=True, exist_ok=True)
    
    # ファイルが存在しない場合はデフォルト設定を作成
    if not config_file.exists():
        try:
            with open(config_file, "w", encoding="utf-8") as f:
                json.dump(default_config, f, indent=2, ensure_ascii=False)
            print(f"デフォルト設定ファイルを作成しました: {config_path}")
        except Exception as e:
            print(f"設定ファイルの作成に失敗しました: {e}")
            return None
    
    # 設定ファイルを読み込み
    try:
        with open(config_file, "r", encoding="utf-8") as f:
            return json.load(f)
    except Exception as e:
        print(f"設定ファイルの読み込みに失敗しました: {e}")
        return default_config

# 使用例
default_settings = {
    "theme": "light",
    "language": "ja",
    "auto_save": True
}

config = ensure_config_file("config/settings.json", default_settings)
print("現在の設定:", config)

実践的なFileNotFoundError対策

1. ファイル管理クラス

import os
import json
import csv
from pathlib import Path
from typing import Optional, List, Dict, Any

class FileManager:
    """安全なファイル操作を提供するクラス"""
    
    def __init__(self, base_path: str = "."):
        self.base_path = Path(base_path)
    
    def ensure_directory(self, dir_path: str) -> bool:
        """ディレクトリの存在を保証"""
        try:
            full_path = self.base_path / dir_path
            full_path.mkdir(parents=True, exist_ok=True)
            return True
        except Exception as e:
            print(f"ディレクトリ作成エラー: {e}")
            return False
    
    def safe_read_text(self, filename: str, encoding: str = "utf-8") -> Optional[str]:
        """安全なテキストファイル読み込み"""
        try:
            file_path = self.base_path / filename
            return file_path.read_text(encoding=encoding)
        except FileNotFoundError:
            print(f"ファイルが見つかりません: {filename}")
            return None
        except Exception as e:
            print(f"ファイル読み込みエラー: {e}")
            return None
    
    def safe_write_text(self, filename: str, content: str, encoding: str = "utf-8") -> bool:
        """安全なテキストファイル書き込み"""
        try:
            file_path = self.base_path / filename
            # ディレクトリが存在しない場合は作成
            file_path.parent.mkdir(parents=True, exist_ok=True)
            file_path.write_text(content, encoding=encoding)
            return True
        except Exception as e:
            print(f"ファイル書き込みエラー: {e}")
            return False
    
    def safe_read_json(self, filename: str) -> Optional[Dict[str, Any]]:
        """安全なJSONファイル読み込み"""
        content = self.safe_read_text(filename)
        if content is None:
            return None
        
        try:
            return json.loads(content)
        except json.JSONDecodeError as e:
            print(f"JSON解析エラー: {e}")
            return None
    
    def safe_write_json(self, filename: str, data: Dict[str, Any]) -> bool:
        """安全なJSONファイル書き込み"""
        try:
            json_content = json.dumps(data, indent=2, ensure_ascii=False)
            return self.safe_write_text(filename, json_content)
        except Exception as e:
            print(f"JSON書き込みエラー: {e}")
            return False
    
    def safe_read_csv(self, filename: str) -> Optional[List[List[str]]]:
        """安全なCSVファイル読み込み"""
        try:
            file_path = self.base_path / filename
            with open(file_path, "r", encoding="utf-8", newline="") as csvfile:
                reader = csv.reader(csvfile)
                return list(reader)
        except FileNotFoundError:
            print(f"CSVファイルが見つかりません: {filename}")
            return None
        except Exception as e:
            print(f"CSV読み込みエラー: {e}")
            return None
    
    def list_files(self, pattern: str = "*") -> List[str]:
        """ファイル一覧の取得"""
        try:
            return [str(p.relative_to(self.base_path)) 
                   for p in self.base_path.glob(pattern) if p.is_file()]
        except Exception as e:
            print(f"ファイル一覧取得エラー: {e}")
            return []

# 使用例
fm = FileManager("./data")

# テキストファイルの操作
content = fm.safe_read_text("notes.txt")
if content:
    print("ノート内容:", content[:50])

success = fm.safe_write_text("output.txt", "処理結果データ")
if success:
    print("ファイルを書き込みました")

# JSONファイルの操作
data = {"name": "田中", "age": 30}
if fm.safe_write_json("user.json", data):
    print("JSONファイルを作成しました")

loaded_data = fm.safe_read_json("user.json")
if loaded_data:
    print("読み込んだデータ:", loaded_data)

# ファイル一覧
files = fm.list_files("*.txt")
print("テキストファイル一覧:", files)

2. 設定ファイル管理システム

class ConfigManager:
    """設定ファイルの管理システム"""
    
    def __init__(self, config_dir: str = "config"):
        self.config_dir = Path(config_dir)
        self.config_dir.mkdir(exist_ok=True)
        self.configs = {}
    
    def load_config(self, name: str, default_config: Dict[str, Any] = None) -> Dict[str, Any]:
        """設定ファイルの読み込み"""
        config_file = self.config_dir / f"{name}.json"
        
        # キャッシュから取得を試行
        if name in self.configs:
            return self.configs[name]
        
        # ファイルから読み込みを試行
        if config_file.exists():
            try:
                with open(config_file, "r", encoding="utf-8") as f:
                    config = json.load(f)
                    self.configs[name] = config
                    return config
            except Exception as e:
                print(f"設定ファイル読み込みエラー ({name}): {e}")
        
        # デフォルト設定を使用
        if default_config is None:
            default_config = {}
        
        self.configs[name] = default_config
        self.save_config(name, default_config)
        return default_config
    
    def save_config(self, name: str, config: Dict[str, Any]) -> bool:
        """設定ファイルの保存"""
        config_file = self.config_dir / f"{name}.json"
        
        try:
            with open(config_file, "w", encoding="utf-8") as f:
                json.dump(config, f, indent=2, ensure_ascii=False)
            self.configs[name] = config
            return True
        except Exception as e:
            print(f"設定ファイル保存エラー ({name}): {e}")
            return False
    
    def get_setting(self, config_name: str, key: str, default=None):
        """特定の設定値を取得"""
        config = self.load_config(config_name)
        return config.get(key, default)
    
    def set_setting(self, config_name: str, key: str, value: Any) -> bool:
        """特定の設定値を更新"""
        config = self.load_config(config_name)
        config[key] = value
        return self.save_config(config_name, config)
    
    def list_configs(self) -> List[str]:
        """利用可能な設定ファイル一覧"""
        try:
            return [f.stem for f in self.config_dir.glob("*.json")]
        except Exception:
            return []

# 使用例
config_manager = ConfigManager()

# アプリケーション設定の管理
app_defaults = {
    "window_width": 800,
    "window_height": 600,
    "theme": "light",
    "auto_save": True
}

app_config = config_manager.load_config("app", app_defaults)
print("アプリ設定:", app_config)

# 設定の更新
config_manager.set_setting("app", "theme", "dark")
print("テーマを変更しました")

# データベース設定の管理
db_defaults = {
    "host": "localhost",
    "port": 5432,
    "database": "myapp",
    "timeout": 30
}

db_config = config_manager.load_config("database", db_defaults)
print("DB設定:", db_config)

# 利用可能な設定一覧
configs = config_manager.list_configs()
print("設定ファイル一覧:", configs)

3. ログファイル管理

import logging
from datetime import datetime

class SafeFileLogger:
    """安全なファイルログ管理"""
    
    def __init__(self, log_dir: str = "logs"):
        self.log_dir = Path(log_dir)
        self.log_dir.mkdir(exist_ok=True)
        self.loggers = {}
    
    def get_logger(self, name: str, level: int = logging.INFO) -> logging.Logger:
        """ロガーの取得"""
        if name in self.loggers:
            return self.loggers[name]
        
        logger = logging.getLogger(name)
        logger.setLevel(level)
        
        # ファイルハンドラーの設定
        log_file = self.log_dir / f"{name}.log"
        try:
            file_handler = logging.FileHandler(log_file, encoding="utf-8")
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
            )
            file_handler.setFormatter(formatter)
            logger.addHandler(file_handler)
        except Exception as e:
            print(f"ログファイル設定エラー: {e}")
        
        self.loggers[name] = logger
        return logger
    
    def safe_log_data(self, filename: str, data: Any) -> bool:
        """データの安全なログ出力"""
        try:
            log_file = self.log_dir / filename
            timestamp = datetime.now().isoformat()
            
            with open(log_file, "a", encoding="utf-8") as f:
                f.write(f"[{timestamp}] {data}\n")
            return True
        except Exception as e:
            print(f"ログ出力エラー: {e}")
            return False
    
    def read_recent_logs(self, filename: str, lines: int = 10) -> Optional[List[str]]:
        """最新のログエントリを読み込み"""
        try:
            log_file = self.log_dir / filename
            if not log_file.exists():
                return []
            
            with open(log_file, "r", encoding="utf-8") as f:
                all_lines = f.readlines()
                return [line.strip() for line in all_lines[-lines:]]
        except Exception as e:
            print(f"ログ読み込みエラー: {e}")
            return None

# 使用例
log_manager = SafeFileLogger()

# アプリケーションログ
app_logger = log_manager.get_logger("application")
app_logger.info("アプリケーションが開始されました")
app_logger.error("エラーが発生しました")

# データログ
log_manager.safe_log_data("data.log", {"user_id": 123, "action": "login"})
log_manager.safe_log_data("data.log", {"user_id": 123, "action": "logout"})

# 最新ログの確認
recent_logs = log_manager.read_recent_logs("data.log", 5)
if recent_logs:
    print("最新のログエントリ:")
    for log_entry in recent_logs:
        print(f"  {log_entry}")

FileNotFoundErrorの予防策

1. パス正規化ユーティリティ

def normalize_path(path: str, base_dir: str = None) -> Path:
    """パスの正規化"""
    path_obj = Path(path)
    
    # 絶対パスの場合はそのまま
    if path_obj.is_absolute():
        return path_obj
    
    # 相対パスの場合はbase_dirを基準にする
    if base_dir:
        return Path(base_dir) / path_obj
    else:
        # スクリプトの場所を基準にする
        import inspect
        caller_file = inspect.stack()[1].filename
        script_dir = Path(caller_file).parent
        return script_dir / path_obj

def find_file_in_paths(filename: str, search_paths: List[str]) -> Optional[Path]:
    """複数のパスからファイルを検索"""
    for search_path in search_paths:
        file_path = Path(search_path) / filename
        if file_path.exists():
            return file_path
    return None

# 使用例
config_paths = [".", "config", "/etc/myapp", "~/.myapp"]
config_file = find_file_in_paths("settings.json", config_paths)

if config_file:
    print(f"設定ファイルを発見: {config_file}")
else:
    print("設定ファイルが見つかりません")

2. ファイル存在確認デコレータ

from functools import wraps

def require_file(filename_param: str):
    """ファイルの存在を確認するデコレータ"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # パラメータからファイル名を取得
            if filename_param in kwargs:
                filename = kwargs[filename_param]
            else:
                # 位置引数から取得(簡略化)
                filename = args[0] if args else None
            
            if filename and not Path(filename).exists():
                raise FileNotFoundError(f"必要なファイルが見つかりません: {filename}")
            
            return func(*args, **kwargs)
        return wrapper
    return decorator

@require_file("config_file")
def load_application_config(config_file: str):
    """設定ファイルを読み込む関数"""
    with open(config_file, "r") as f:
        return json.load(f)

# 使用例
try:
    config = load_application_config("app_config.json")
    print("設定を読み込みました")
except FileNotFoundError as e:
    print(f"エラー: {e}")

まとめ

FileNotFoundErrorはファイル操作で最も頻出するエラーですが、適切な対策で効果的に防げます。

重要なポイント:

  • 事前確認:os.path.exists()やPathlib.exists()でファイル存在確認
  • try-except:包括的な例外処理でエラーハンドリング
  • pathlib活用:モダンなパス操作でクロスプラットフォーム対応
  • ディレクトリ作成:makedirs()で必要なディレクトリを事前作成
  • デフォルト対応:ファイルがない場合のデフォルト処理を用意
  • ログ管理:エラーの詳細情報を適切に記録

FileNotFoundErrorを理解し、適切に対処することで、より堅牢で信頼性の高いファイル操作プログラムを作成できます。特にデータ処理や設定管理では、このエラーへの対策が品質向上の鍵となります。

「らくらくPython塾」が切り開く「呪文コーディング」とは?

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座

フリーランスボード

20万件以上の案件から、副業に最適なリモート・週3〜の案件を一括検索できるプラットフォーム。プロフィール登録でAIスカウトが自動的にマッチング案件を提案。市場統計や単価相場、エージェントの口コミも無料で閲覧可能なため、本業を続けながら効率的に高単価の副業案件を探せます。フリーランスボード

ITプロパートナーズ

週2〜3日から働ける柔軟な案件が業界トップクラスの豊富さを誇るフリーランスエージェント。エンド直契約のため高単価で、週3日稼働でも十分な報酬を得られます。リモートや時間フレキシブルな案件も多数。スタートアップ・ベンチャー中心で、トレンド技術を使った魅力的な案件が揃っています。専属エージェントが案件紹介から契約交渉までサポート。利用企業2,000社以上の実績。ITプロパートナーズ

Midworks 10,000件以上の案件を保有し、週3日〜・フルリモートなど柔軟な働き方に対応。高単価案件が豊富で、報酬保障制度(60%)や保険料負担(50%)など正社員並みの手厚い福利厚生が特徴。通勤交通費(月3万円)、スキルアップ費用(月1万円)の支給に加え、リロクラブ・freeeが無料利用可能。非公開案件80%以上、支払いサイト20日で安心して稼働できます。Midworks