Pythonでファイルを操作する際に発生する「FileNotFoundError」を分かりやすく解説!原因と解決策、代替手段も紹介


「FileNotFoundError」は、Pythonでファイル操作中に発生する例外エラーの一つです。これは、プログラムがアクセスしようとしているファイルが存在しない場合に発生します。このエラーは、ファイルのパスミス、ファイル名の誤り、ファイルの削除など、様々な原因によって発生する可能性があります。

エラーの例

try:
  with open('myfile.txt', 'r') as f:
    content = f.read()
except FileNotFoundError:
  print('ファイルが見つかりませんでした。')

このコード例では、myfile.txtというファイルを r モードで開こうとしています。しかし、ファイルが存在しないため、FileNotFoundError例外が発生し、「ファイルが見つかりませんでした。」というメッセージが表示されます。

原因

「FileNotFoundError」が発生する主な原因は以下の通りです。

  • アクセス権限の不足: ファイルへのアクセス権限がない場合、プログラムはファイルを開くことができず、エラーが発生します。
  • ファイルの削除: プログラムが実行される前にファイルが削除されると、プログラムはファイルにアクセスできなくなり、エラーが発生します。
  • ファイル名の誤り: ファイル名を間違えると、プログラムは正しいファイルを見つけることができず、エラーが発生します。
  • ファイルパスの誤り: ファイルのパスを間違えると、プログラムはファイルを見つけることができず、エラーが発生します。

解決策

「FileNotFoundError」を解決するには、以下の対策を行うことができます。

  • アクセス権限の確認: ファイルへのアクセス権限を持っていることを確認してください。
  • ファイルの存在確認: プログラムを実行する前に、ファイルが存在することを確認してください。
  • ファイル名の確認: ファイル名を正しく記述していることを確認してください。
  • ファイルパスの確認: ファイルパスが正しいことを確認してください。相対パスを使用する場合は、カレントワーキングディレクトリを考慮する必要があります。

予防策

「FileNotFoundError」を予防するには、以下の点に注意する必要があります。

  • 例外処理: ファイル操作中に発生する可能性のあるエラーを考慮し、適切な例外処理を行うようにしましょう。
  • ファイルの存在確認: ファイルにアクセスする前に、os.path.exists()などの関数を使用してファイルの存在を確認するようにしましょう。
  • ファイル名の記述: ファイル名は分かりやすく、一意な名前にしましょう。
  • ファイルパスの記述: ファイルパスは明確かつ簡潔に記述するようにしましょう。
  • ファイル操作には、os モジュールや pathlib モジュールなどのライブラリを使用することができます。
  • Python 3.3以降では、FileNotFoundErrorOSError のサブクラスになっています。


ファイルパスミスによる「FileNotFoundError」

try:
  with open('missing_file.txt', 'r') as f:
    content = f.read()
except FileNotFoundError:
  print('ファイルが見つかりませんでした: missing_file.txt')

このコードでは、missing_file.txtというファイルが存在しないため、FileNotFoundErrorが発生し、「ファイルが見つかりませんでした: missing_file.txt」というメッセージが表示されます。

try:
  with open('myfile.csv', 'r') as f:
    content = f.read()
except FileNotFoundError:
  print('ファイルが見つかりませんでした: myfile.csv')

このコードでは、ファイル名は正しく記述されていますが、実際にはmyfile.txtというファイルが存在するため、FileNotFoundErrorが発生し、「ファイルが見つかりませんでした: myfile.csv」というメッセージが表示されます。

def read_file(filename):
  try:
    with open(filename, 'r') as f:
      content = f.read()
      print(f'ファイルの内容: {content}')
  except FileNotFoundError:
    print(f'ファイルが見つかりませんでした: {filename}')

read_file('myfile.txt')  # ファイルが存在する場合
read_file('missing_file.txt')  # ファイルが存在しない場合

このコードでは、read_fileという関数を作成し、ファイルの読み取りと例外処理を行います。read_file関数には、読み取るファイル名の引数filenameが渡されます。

  • ファイルが存在しない場合、FileNotFoundError例外を捕捉し、ファイル名と合わせて「ファイルが見つかりませんでした」というメッセージをコンソールに表示します。
  • ファイルが存在する場合、ファイルの内容を読み込み、コンソールに表示します。


代替手段の選択肢

  1. ファイルの存在確認: ファイルが存在するかどうかを事前に確認し、存在しない場合は処理をスキップまたは別の処理を実行します。
  2. デフォルト値の提供: ファイルが存在しない場合に使用するデフォルト値を設定し、プログラムのロジックを維持します。
  3. 例外処理のロジカルな拡張: より詳細な例外処理を行い、エラーの種類や状況に応じて適切なメッセージや処理を実行します。

具体的な代替手段

以下に、上記3つの選択肢に基づいた具体的な代替手段をいくつか紹介します。

ファイルの存在確認

def read_file(filename):
  if os.path.exists(filename):
    with open(filename, 'r') as f:
      content = f.read()
      print(f'ファイルの内容: {content}')
  else:
    print(f'ファイルが見つかりませんでした: {filename}')

read_file('myfile.txt')
read_file('missing_file.txt')

この例では、os.path.exists()関数を使用してファイルの存在を確認しています。ファイルが存在する場合は読み込みを行い、存在しない場合は「ファイルが見つかりませんでした」というメッセージを表示します。

デフォルト値の提供

def read_file(filename, default_content=''):
  try:
    with open(filename, 'r') as f:
      content = f.read()
  except FileNotFoundError:
    content = default_content
  print(f'ファイルの内容: {content}')

read_file('myfile.txt')
read_file('missing_file.txt')

この例では、default_contentという引数にデフォルト値を設定しています。ファイルが存在する場合は読み込みを行い、存在しない場合はデフォルト値を使用します。

例外処理のロジカルな拡張

def read_file(filename):
  try:
    with open(filename, 'r') as f:
      content = f.read()
      print(f'ファイルの内容: {content}')
  except FileNotFoundError as e:
    if e.errno == errno.ENOENT:  # ファイルが見つからない
      print(f'ファイルが見つかりませんでした: {filename}')
    else:  # その他のエラー
      print(f'予期せぬエラーが発生しました: {e}')

read_file('myfile.txt')
read_file('missing_file.txt')

この例では、except FileNotFoundError内の処理を拡張し、e.errno属性を使用してエラーの詳細を確認しています。errno.ENOENTの場合は「ファイルが見つかりませんでした」というメッセージを表示し、それ以外のエラーの場合は「予期せぬエラーが発生しました」というメッセージを表示します。

代替手段の選択

上記の代替手段はそれぞれ異なる利点と欠点があります。状況に応じて適切な手段を選択することが重要です。

  • 例外処理のロジカルな拡張: 詳細なエラー処理を行うことができますが、複雑なコードになり、メンテナンスが困難になる可能性があります。
  • デフォルト値の提供: デフォルト値を使用することで、プログラムのロジックを維持することができますが、必ずしも必要な情報が得られない場合があります。
  • ファイルの存在確認: シンプルでわかりやすい処理ですが、毎回ファイルの存在を確認するため、処理速度が低下する可能性があります。

上記以外にも、状況に応じて様々な代替手段が考えられます。例えば、ログファイルへの記録、エラーメッセージの送信、再試行処理の実装などが挙げられます。