ファイルと例外

実際に動作するほとんどのプログラムはファイルシステムを操作します:設定を読み込む、結果を書き込む、データを読み込む。そして何か問題が起きたとき、Pythonは例外を発生させます。これは予期しないことが起きたことを示す信号です。この章では両方をカバーします:ファイルの出入力、そして優雅にエラーを処理して、クラッシュしないコードを書くこと。
ファイルを開く
open()はファイルを開いて、読み込みまたは書き込みができるオブジェクトを返します。パスと、ファイルで何をしたいか(読み込み、書き込み、追記)を指定します。ファイルが終わったら必ずクローズします。withステートメントはこれを自動的に行います。
f = open("data.txt", "r") # "r" = 読み込み
content = f.read()
f.close()"r"はモードです:
| モード | 意味 |
|---|---|
"r" | 読み込み。ファイルは存在していなければなりません。デフォルトモード。 |
"w" | 書き込み。ファイルを作成または上書きします。 |
"a" | 追記。削除せずに末尾に追加します。 |
"x" | 作成。ファイルが既に存在する場合は失敗します。 |
"r+" | 読み込みと書き込み。 |
"b" | バイナリ。任意のモードに追加:"rb"、"wb"。 |
完了したら必ず.close()を呼び出してください。忘れるとファイルが開いたままになり、書き込まれるのを待っているデータを失う可能性があります。これを処理する確実な方法はwithステートメントです。
open(path, mode)はファイルオブジェクトを提供し、モードは何をしたいかを言います:"r"で読み込み、"w"で書き込み(そこにあるものをすべて消す)、"a"で末尾に追加。私は一度"w"で誤ってファイルを失いました。"a"のつもりだったのに、だからタイプする前にモードの図を思い浮かべてください。 withステートメント
with open(...)はファイルを管理し、インデントされたブロックが終了するとき自動的にそれをクローズします。エラーが発生した場合でも。常にwith open(...)を使用してください。手動のopen()/close()の代わりに。それはより安全で、それが標準です。
with open("data.txt", "r") as f:
content = f.read()
# fはここでクローズされた、保証付きwithはPythonのコンテキストマネージャ構文です:セットアップとティアダウンコードを実行してくれます。ここではファイルを開いて、信頼できる方法でそれをクローズします。open()で使用するにはどのように内部で機能するかを知る必要はありません。
with open(...) as fファイルを開き、インデントされたブロック内でfで動作させ、ブロックが終了するときそれをクローズしてくれます。何か問題が起こった場合でも。手動で.close()を呼び出す代わりに毎回それに達してください。忘れることが1つ少なくなります。 ファイルを読み込む
読み込みの3つの方法。.read()はファイル全体を1つの文字列として読み込みます。.readline()は1行を読み込みます。ファイルオブジェクトを直接反復することは行ごとに読み込みます。これは大きなファイルの最も効率的なアプローチです。すべてをメモリに一度に読み込まないため。
with open("data.txt", "r") as f:
content = f.read() # ファイル全体を1つの文字列として
with open("data.txt", "r") as f:
first_line = f.readline() # 一度に1行
with open("data.txt", "r") as f:
lines = f.readlines() # 行のリスト。各行は"\n"で終わる大きなファイルの場合、すべてを一度に読み込むより行ごとに読み込む方が効率的です:
with open("big_file.txt", "r") as f:
for line in f: # ファイルを直接反復。メモリ効率的
print(line.strip()) # strip()は末尾の改行を削除ファイルオブジェクトを直接反復処理する(for line in f)は大きなファイルを読み込む最も効率的な方法です。
.read()はファイル全体を1つの文字列として提供し、.readline()は単一行を提供します。ファイルが大きい可能性がある場合、`for line in f`で代わりにループします。一度に1行を読み込むので、メモリに多数を読み込みません。各行の`.strip()`は末尾の改行をクリアします。 ファイルに書き込む
"w"モードはファイルが存在する場合は完全に上書きします。"a"モードは末尾に追加します。.write()は自動的に改行を追加しません。各行の末尾に明示的に"\n"を含めます。一度に複数の行を書き込むには、"\n".join()でそれらを結合します。
with open("output.txt", "w") as f:
f.write("Tokyo\n")
with open("output.txt", "a") as f:
f.write("別の行\n")"w"はファイルが存在する場合、完全に上書きします。"a"は末尾に追加します。
f.write()は自動的に改行を追加しません。だから明示的に"\n"を含めます。一度に複数の行を書き込むには:
lines = ["最初の行", "2番目の行", "3番目の行"]
with open("output.txt", "w") as f:
f.write("\n".join(lines) + "\n")"w"はファイルを作成または上書きします。`"a"`は消さずに末尾に追加します。.write()は自動的に改行を追加しません。だから自分で各行に"\n"を付けます。行のバッチの場合、"\n".join(lines)はそれらを最初に一緒に繋ぎます。 例外
Pythonが処理できない問題に遭遇すると、例外を発生させます:何が起きたのか、どこで起きたのかを説明するエラー。処理しない場合、プログラムがクラッシュして、トレースバックを出力します。下の表は、あなたが遭遇する最も一般的な例外を示しています。
あなたが遭遇する一般的な例外:
| 例外 | それが起きるとき |
|---|---|
FileNotFoundError | open()がファイルを見つけられません |
ValueError | 関数は正しい型だが間違った内容の値を取得します。例えばint("abc") |
TypeError | 完全に間違った型。例えば"hello" + 5 |
KeyError | 辞書キーが存在しません |
IndexError | リストのインデックスが範囲外 |
ZeroDivisionError | ゼロで除算 |
AttributeError | オブジェクトはその属性またはメソッドを持ちません |
FileNotFoundError、ValueError、KeyError、TypeError。未処理のままになると、プログラムを停止してトレースバックを出力します。これはアラーム的に見えますが、実際には、それが壊れた場所に直接指す地図です。 try / except
失敗する可能性のあるコードをtryブロックでラップします。例外が発生した場合、マッチするexceptブロックがクラッシュの代わりにそれを処理します。どの例外をキャッチするかについて具体的にしてください:裸のexcept:ですべてをキャッチすることは実際のバグを隠します。
try:
value = int("abc")
except ValueError:
print("これは有効な番号ではありません")キャッチする例外について具体的にしてください。すべての例外を裸のexcept:でキャッチすることはバグを隠します:
# 悪い。プログラマーの間違いを含め、すべてをキャッチ
try:
result = do_something()
except:
pass
# 良い。期待して、実際に処理できるものだけをキャッチ
try:
result = do_something()
except FileNotFoundError:
print("ファイルが見つかりません")tryブロックに入れ、マッチするexceptがプログラムをクラッシュの代わりに実行します。ValueErrorのような期待する例外の名前を付けてください。すべてをキャッチする裸のexcept:ではなく。実際に対処できるものをキャッチし、残りを表示させます。 複数の例外をキャッチする
異なるエラー型を別々のexceptブロックで処理したり、タプルを使用して1つのブロックで複数の型をキャッチできます。as e部分はエラーメッセージへのアクセスを提供します。
try:
data = int(user_input)
result = 100 / data
except ValueError:
print("番号ではありません")
except ZeroDivisionError:
print("ゼロで除算することはできません")またはタプルで複数をキャッチ:
except (ValueError, ZeroDivisionError) as e:
print(f"入力エラー:{e}")as eは例外オブジェクトを名前にバインドするので、メッセージを検査できます。
exceptブロックを指定し、Pythonが最初のマッチを実行します。いくつかを同じ方法で処理するために、タプルでそれらをリストアップしてください:except (ValueError, ZeroDivisionError)。as e部分はエラーオブジェクトを提供するので、そのメッセージを出力できます。 else と finally
elseは例外が発生しなかった場合にのみ実行されます。finallyは常に実行されます。例外があるか否か関係なく。finallyは、結果に関わらず何が起ころうとも実行されなければならないクリーンアップに役立ちます。
try:
with open("data.txt") as f:
content = f.read()
except FileNotFoundError:
print("ファイルが見つかりません。デフォルトを使用")
content = ""
else:
print("ファイルが正常に読み込まれました")
finally:
print("ファイルの読み込み試行が完了しました") # 常に実行finallyはクリーンアップに最も役立ちます(接続をクローズ、ロックをリリース)。ファイルに既にwithを使用している場合でも。
elseは`try`が何も発生しない場合にのみ実行されます。成功パスの残りのための整理された場所。finallyは常に実行されます。例外の有無。だから結果に関わらず何が起ころうとも実行される必要があるクリーンアップのためのスポット。ファイルで`with`は既にクリーンアップをカバーするので、あなたが予想するより`finally`に達することは少なくなります。 raise
raiseで自分自身の例外を発生させることができます。これはあなたのプログラムを呼び出し者に問題を明確に信号するために、間違った値を静かに返す代わりに機能させる方法です。
def divide(a, b):
if b == 0:
raise ValueError("ゼロで除算することはできません")
return a / bこれはあなたの関数を期待し、問題を明確に呼び出し者に信号します。
raise ExceptionType("message")はあなたのコードが悪い値を続行する代わりに、問題を大きく旗立てさせます。関数がこれを言う方法「これで作業することはできません」だから呼び出し者がそれを扱います。明確で早いは、後で表示する間違った答えを打ちます。 カスタム例外クラス
より大きなプログラムのために、Exceptionから継承することで、自分の例外型を定義できます。これは呼び出し者が、他の種類のエラーから、あなたの特定のエラーを個別にキャッチさせます。
class InsufficientFundsError(Exception):
pass
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
if amount > self.balance:
raise InsufficientFundsError(
f"{amount}を引き出すことはできません。残高は{self.balance}です"
)
self.balance -= amounttry:
account.withdraw(1000)
except InsufficientFundsError as e:
print(f"トランザクションが拒否されました:{e}")JSON
JSONはすべてが話す形式です:API。設定ファイル。データエクスポート。Pythonのjsonモジュールはそれを直接処理します。json.load()はファイルからJSONをPython辞書またはリストに読み込みます。json.dump()は辞書またはリストをファイルに戻してJSONを書き込みます。
ファイルからJSONを読み込む:
import json
with open("config.json", "r") as f:
config = json.load(f) # JSONをPython辞書/リストに解析
print(config["setting"])ファイルにJSONを書き込む:
import json
data = {"name": "太郎", "score": 87, "active": True}
with open("output.json", "w") as f:
json.dump(data, f, indent=2) # indent=は人間が読めるようにしますJSONからPython型へのマッピング:
| JSON | Python |
|---|---|
object {} | dict |
array [] | list |
string "" | str |
| number | int または float |
true / false | True / False |
null | None |
ファイルを触らずにJSON文字列とPythonオブジェクトの間に変換する:
import json
# 文字列からPython
data = json.loads('{"name": "太郎", "score": 87}')
# PythonからString
text = json.dumps({"name": "太郎", "score": 87}, indent=2)json.load()はファイルオブジェクトから読み込みます。json.loads()(sを持つ)は文字列から読み込みます。
json.load(f)ファイルのJSONをPython辞書とリストに変わります。`json.dump(data, f)`はそれらを戻し出力します。`s`バージョン。`json.loads`と`json.dumps`ファイルの代わりに文字列のために同じことをしてください。出力を読めるようにしたいときに`indent=2`を追加してください。 実践で
小さなゲームの保存/読み込みパターン:状態をJSONに書き込み。次の実行時に読み込み。そして保存ファイルがまだ存在しない場合、デフォルトにフォールバック:
import json
SAVE_FILE = "save_game.json"
def save_game(player_data: dict) -> None:
with open(SAVE_FILE, "w") as f:
json.dump(player_data, f, indent=2)
print("ゲームが保存されました。")
def load_game() -> dict:
try:
with open(SAVE_FILE, "r") as f:
return json.load(f)
except FileNotFoundError:
print("保存ファイルが見つかりません。新規開始。")
return {"name": "プレイヤー", "score": 0, "level": 1}
state = load_game()
state["score"] += 50
save_game(state)
