Skip to content
This page has been auto-translated and may contain errors.View in English

ファイルと例外

docs.scrimba.com

実際に動作するほとんどのプログラムはファイルシステムを操作します:設定を読み込む、結果を書き込む、データを読み込む。そして何か問題が起きたとき、Pythonは例外を発生させます。これは予期しないことが起きたことを示す信号です。この章では両方をカバーします:ファイルの出入力、そして優雅にエラーを処理して、クラッシュしないコードを書くこと。

ファイルI/Oと例外処理は、プログラムを信頼できるものにする2つのメカニズムです。open()がファイルシステムへのアクセスを提供し、withがエラーが発生した場合でもファイルが確実にクローズされることを保証します。try/exceptは特定の例外型をキャッチするので、クラッシュする代わりに回復できます。これらが一緒に、無人で実行されるスクリプトの基礎を形成します。

ファイルと例外は、スクリプトが汚い外部世界と出会う場所です:存在しないパス、満杯のディスク、解析できない入力。open()はファイルオブジェクトを返し、withはコードの中で例外が発生した場合でもそれがクローズされることを保証します。例外は、Pythonがその失敗を信号する方法です:例外が発生すると、それを引き起こしたコールを通じて上に向かって移動し、その経路沿いで最初にマッチするexceptがそれを処理します。この章が強調する規律は、実際に回復できる特定の失敗をキャッチして、残りのものは大きく表面化させることであり、すべてを飲み込んでしまって、無音で失敗するスクリプトを出荷するのではなく。

ファイルを開く

open()はファイルを開いて、読み込みまたは書き込みができるオブジェクトを返します。パスと、ファイルで何をしたいか(読み込み、書き込み、追記)を指定します。ファイルが終わったら必ずクローズします。withステートメントはこれを自動的に行います。

open(path, mode)はファイルオブジェクトを返します。モード文字列はアクセスを制御します:"r"は読み込み、"w"は書き込み(最初にファイルをクリア)、"a"は末尾に追記します。ファイルがテキストでない場合は"b"を追加してバイナリモードにします。最初の日からセットする価値のあることが1つあります:テキストファイルにencoding="utf-8"を渡します。それを省略すると、Pythonはマシンのデフォルトが何であれそれを使用するので、ノートパソコンで正常に読み込まれるファイルが、他人のマシンで破損した文字を返す可能性があります。

open()はOSにファイルのハンドルを要求し、それの周りにラップされたファイルオブジェクトを返します。モードはアクセス("r""w""a")とテキストか生バイトか("b")の両方を選びます。人々を困らせるパラメータはencodingです:これはディスク上のバイトがどのように文字にマップするかを決めます。それを設定しないままにすると、Pythonはマシンのロケールのデフォルトにフォールバックし、これはプラットフォーム間で異なるので、あるマシンで書き込まれたファイルが別のマシンで間違ってデコードされる可能性があります。テキストに対して常にencoding="utf-8"を渡します。何か特別な理由がない限り、ほとんどの驚きが消えます。

python
f = open("data.txt", "r")    # "r" = 読み込み
content = f.read()
f.close()

"r"モードです:

モード意味
"r"読み込み。ファイルは存在していなければなりません。デフォルトモード。
"w"書き込み。ファイルを作成または上書きします。
"a"追記。削除せずに末尾に追加します。
"x"作成。ファイルが既に存在する場合は失敗します。
"r+"読み込みと書き込み。
"b"バイナリ。任意のモードに追加:"rb""wb"

完了したら必ず.close()を呼び出してください。忘れるとファイルが開いたままになり、書き込まれるのを待っているデータを失う可能性があります。これを処理する確実な方法はwithステートメントです。

Junoファイルを開くopen(path, mode)はファイルオブジェクトを提供し、モードは何をしたいかを言います:"r"で読み込み、"w"で書き込み(そこにあるものをすべて消す)、"a"で末尾に追加。私は一度"w"で誤ってファイルを失いました。"a"のつもりだったのに、だからタイプする前にモードの図を思い浮かべてください。
Junoファイルを開くopen(path, mode)はファイルオブジェクトを返します:"r"読み込み、"w"上書き、"a"追記、プラス"b"バイナリ用。テキストファイルにencoding="utf-8"を渡すので、あらゆるマシンで同じように読み込まれ、withにクローズを処理させます。
Junoファイルを開くopen()はOSハンドル上のファイルオブジェクトを提供します。モードはアクセスとテキスト対バイトを設定します。悪く移動するのはencodingの設定です:それを切ったままにするとマシンのロケールデフォルトを継承するので、テキストに対してencoding="utf-8"を習慣にしてください。withが行うとき、手で.close()に寄りかからないでください。

withステートメント

with open(...)はファイルを管理し、インデントされたブロックが終了するとき自動的にそれをクローズします。エラーが発生した場合でも。常にwith open(...)を使用してください。手動のopen()/close()の代わりに。それはより安全で、それが標準です。

withはPythonのコンテキストマネージャ構文です:ブロックが開始するときに「セットアップ」呼び出しが実行され、ブロックが終了するときに「ティアダウン」呼び出しが実行される小さなプロトコルです。ファイルの場合、セットアップはオープンファイルを返し、ティアダウンはそれをクローズします。利点は、ブロック内で例外が発生した場合でもティアダウンが実行されるので、すべてのファイルの周りに手動でtry/finallyを書くことなく、そのクリーンアップを取得できることです。

コンテキストマネージャwithの後に配置できる任意のオブジェクト)は2つの動作を定義します:入り方と出る方法。with open(...) as fは入り方のステップを実行し、ファイルをfにバインドし、アウトステップを登録します。これはブロックが終了するときにPythonが実行し、通常終了したか例外が発生したかに関わらず。ファイルの場合、アウトステップはclose()です。2つの実践的なメモ。1つのステートメントで複数のファイルを開くことができます。with open(a) as f, open(b) as g:、そして両方が順序でクローズします。そしてアウトステップは例外を飲み込むことを選択できます。これはcontextlib.suppress(FileNotFoundError)のようなヘルパーがどのように機能するかであり、したがってwithブロックがコンテキストマネージャが書くとき静かにエラーを吸収できることを知ってください。

python
with open("data.txt", "r") as f:
    content = f.read()

# fはここでクローズされた、保証付き

withはPythonのコンテキストマネージャ構文です:セットアップとティアダウンコードを実行してくれます。ここではファイルを開いて、信頼できる方法でそれをクローズします。open()で使用するにはどのように内部で機能するかを知る必要はありません。

Junowithステートメントwith open(...) as fファイルを開き、インデントされたブロック内でfで動作させ、ブロックが終了するときそれをクローズしてくれます。何か問題が起こった場合でも。手動で.close()を呼び出す代わりに毎回それに達してください。忘れることが1つ少なくなります。
Junowithステートメントwithブロックが開いたときセットアップを実行し、それが閉じたときクリーンアップを実行し、クリーンアップは例外時でも発火します。ファイルの場合そのクリーンアップは`close()`なので、1つを書くことなく`try`/`finally`安全を取得します。手動で毎回`open()`/`close()`より優先してください。
Junowithステートメント コンテキストマネージャはブロックが出るときにファイルをクローズします。ブロックが終了したか例外が発生したかに関わらず、したがって`with`は手書きの`try`/`finally`をクリーンアップで置き換えます。1つで複数を開いてください。`with`。アウトステップが例外を抑制できることを心に留めておいてください。これはまさに`contextlib.suppress`が何のためのものであり、`with`ブロックがエラーを飲み込むとき認識する価値があります。

ファイルを読み込む

読み込みの3つの方法。.read()はファイル全体を1つの文字列として読み込みます。.readline()は1行を読み込みます。ファイルオブジェクトを直接反復することは行ごとに読み込みます。これは大きなファイルの最も効率的なアプローチです。すべてをメモリに一度に読み込まないため。

.read()はファイル全体をメモリに1つの文字列として読み込みます。.readline()は単一行を読み込み、改行を含みます。.readlines()はすべての行のリストを返します。大きい可能性のあるものの場合、for line in fでファイルオブジェクトを直接反復処理します:一度に1行を引き出し、次に進む前に完全なファイルを一度も保持しないので、メモリはサイズに関わらず平坦なままです。

.read()はファイル全体を1つの文字列として返すので、メモリコストはファイルサイズで拡張します:設定には良いですが、マルチギガバイトログには問題です。ファイルオブジェクトを反復処理します。for line in fは1行ずつ読み込み、次の前にそれを破棄するので、メモリは長さに関わらず平坦なままです。それがデフォルトでするパターンです。不明な大きさのファイルのために。.readlines()は便利に見えますが、一度にすべての行のリストを構築し、メモリフットプリントが.read()と同じであるため、ループ上で何も購入しません。メモリ不足のバグを防ぐ規則:最初にfor line in fループに達しましょう。そしてopen()に呼び出す.read()だけになってください。ファイルが小さいことを知っている場合。

python
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"で終わる

大きなファイルの場合、すべてを一度に読み込むより行ごとに読み込む方が効率的です:

python
with open("big_file.txt", "r") as f:
    for line in f:              # ファイルを直接反復。メモリ効率的
        print(line.strip())     # strip()は末尾の改行を削除

ファイルオブジェクトを直接反復処理する(for line in f)は大きなファイルを読み込む最も効率的な方法です。

Junoファイルを読み込む.read()はファイル全体を1つの文字列として提供し、.readline()は単一行を提供します。ファイルが大きい可能性がある場合、`for line in f`で代わりにループします。一度に1行を読み込むので、メモリに多数を読み込みません。各行の`.strip()`は末尾の改行をクリアします。
Junoファイルを読み込む.read()はすべてを一度に読み込み、これは小さいファイルには問題ありませんが大きいものには危険です。デフォルトを`for line in f`にしてください:一度に1行ストリームしたままメモリを平坦なままです。サイズに関わらず。`.readlines()`は見栄えが良いが、`.read()`と同じメモリを使用します。
Junoファイルを読み込む.read().readlines()の両方がファイル全体をメモリに保持するため、ファイルサイズで拡張します。`for line in f`ループは一度に1行を読み込み、保持を落とすので、メモリは平坦なままです。これはメモリ不足の驚きを停止するものです。最初にループに達してください。`open()`だけが小さいとわかっているときに。

ファイルに書き込む

"w"モードはファイルが存在する場合は完全に上書きします。"a"モードは末尾に追加します。.write()は自動的に改行を追加しません。各行の末尾に明示的に"\n"を含めます。一度に複数の行を書き込むには、"\n".join()でそれらを結合します。

.write(s)は1つの文字列を書き込み、print()と異なり、何も追加しません。スペースと改行がありません。だから"\n"を自分で入れます。.writelines(lines)はリストの各文字列を背中合わせで書き込み、分離器は追加されません。だから改行は既にあなたの文字列にあります。モードに注意してください:"w"はあなたが何かを書いた前に、開いた瞬間にファイルをクリアします。だから"w"で開く場合、"a"のつもりだったが、古い内容を破棄します。

書き込みについて2つのこと。実際のバグを引き起こします。まず、あなたが書く데이터は必ずしも直後にディスクを打つわけではありません:OSはバッファに保持し、バッチで書き込み、.close()withがそれを呼び出す)がすべてがディスク上にあることを確認します。長時間実行されるプロセスが書き込み、クローズしない場合、出力の末尾はバッファにでき、クラッシュで失われる可能性があります。だからファイルをクローズするか、.flush()を呼び出します。データが安全である必要があるポイントで。2番目、モードは損害を決めます:"w"は開いた瞬間ファイルを空にし、何かを書く前に、だから"w"に達しようとした場合、"a"のつもりだったが、警告なしに以前の内容を破壊します。.writelines(lines)は分離器を追加しません。だから改行は既に文字列にあります。

python
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"を含めます。一度に複数の行を書き込むには:

python
lines = ["最初の行", "2番目の行", "3番目の行"]

with open("output.txt", "w") as f:
    f.write("\n".join(lines) + "\n")
Junoファイルに書き込む"w"はファイルを作成または上書きします。`"a"`は消さずに末尾に追加します。.write()は自動的に改行を追加しません。だから自分で各行に"\n"を付けます。行のバッチの場合、"\n".join(lines)はそれらを最初に一緒に繋ぎます。
Junoファイルに書き込む"w"はそれが開く瞬間ファイルをクリアし、"a"は追記するので、間違った1つを選ぶと静かに古い内容を投げ捨てます。.write()は何も追加しません。改行がないので、自分で"\n"を提供します。.writelines()も分離器を追加しません。改行は既に文字列にあります。
Junoファイルに書き込む"w"は開いた瞬間ファイルを空にするので、`"a"`の代わりに達すると警告なしに以前の内容を破壊します。書き込みはバッファに座り、.close()(`with`がそれを呼び出す)がそれらをフラッシュするまで。だからプロセスが書き込みしてクローズしない場合、その末尾はクラッシュで失われる可能性があります。.write().writelines()は改行を追加しません。これはあなた次第です。

例外

Pythonが処理できない問題に遭遇すると、例外を発生させます:何が起きたのか、どこで起きたのかを説明するエラー。処理しない場合、プログラムがクラッシュして、トレースバックを出力します。下の表は、あなたが遭遇する最も一般的な例外を示しています。

例外はオブジェクトであり、例外は家族の木を形成します:FileNotFoundErrorのような特定のものはより広い1つ(OSError)の一種であり、キャッチするほぼすべてのものはExceptionの一種です。その木は捕捉がどのように機能するかです:親型をキャッチするとその子もキャッチします。1つが発生すると、Pythonは現在の行を放棄し、そこに至ったコールを通じて逆に歩きます。マッチするexceptを探します。見つからない場合、プログラムは停止し、トレースバックを出力します:エラーが起きたところから上までのコールのリスト。

例外はクラス階層(型の家族の木)を形成し、その木はキャッチするときの全体のゲームです:親型のexceptも下のすべての型をキャッチするため、except Exceptionは広いネットであり、except FileNotFoundErrorは狭いものです。覚える価値のある木の1つの部分は、KeyboardInterrupt(ユーザーがCtrl-Cを押す)とSystemExit(クリーンシャットダウン要求)がExceptionの下にではなく、その横にあります。それは意図的です:広いexcept Exceptionがそれら2つを通す意味なので、Ctrl-Cは、それをキャッチの中でさえプログラムを停止します。これはまさに、あなたがexcept Exceptionに達しませんし、決して裸のexcept:に達しない理由です。これはそれら2つをキャッチし、ユーザーをプログラムの内部に閉じ込めます。彼らは終了しようとしています。

あなたが遭遇する一般的な例外:

例外それが起きるとき
FileNotFoundErroropen()がファイルを見つけられません
ValueError関数は正しい型だが間違った内容の値を取得します。例えばint("abc")
TypeError完全に間違った型。例えば"hello" + 5
KeyError辞書キーが存在しません
IndexErrorリストのインデックスが範囲外
ZeroDivisionErrorゼロで除算
AttributeErrorオブジェクトはその属性またはメソッドを持ちません
Juno例外 例外はPythonが何か起きたことを言っています。あなたは常に数人を遭遇します:FileNotFoundErrorValueErrorKeyErrorTypeError。未処理のままになると、プログラムを停止してトレースバックを出力します。これはアラーム的に見えますが、実際には、それが壊れた場所に直接指す地図です。
Juno例外 例外はオブジェクトで家族の木に配置された、親型をキャッチするもその子もキャッチしてくれます。1つが発生するとPythonはマッチする`except`を探して、コールを通じて逆に歩きます。見つからない場合トレースバックを出力します。一般的な名前を知る、ValueErrorKeyErrorFileNotFoundErrorはあなたが正しいものをキャッチするようにします。
Juno例外 型階層は全体のポイントです:except Exceptionは広いネット。特定の型は狭いものです。KeyboardInterruptSystemExitは`Exception`の下ではなく、その横に座ります。だからCtrl-Cは`except Exception`を逃げます。これはそれ、`except:`の裸の上で使用する理由です。これはユーザーをプログラムの内部に閉じ込めます。彼らは終了しようとしています。

try / except

失敗する可能性のあるコードをtryブロックでラップします。例外が発生した場合、マッチするexceptブロックがクラッシュの代わりにそれを処理します。どの例外をキャッチするかについて具体的にしてください:裸のexcept:ですべてをキャッチすることは実際のバグを隠します。

try/exceptは特定の例外型をキャッチし、クラッシュの代わりにハンドラを実行します。型の命名は重要です:実際に回復できるものをキャッチするので、関係のないバグは大きく表面化され、飲み込まれません。例外でas eをバインドして、そのメッセージを読みたいとき。異なる型に対して複数のexcept句をリストし、Pythonは最初のマッチするものを使用します。

except SomeTypeは、発生した例外がその型またはそれのサブタイプ(木の下のより特定の種類)のときマッチします。これは、親をキャッチするもそのすべての子をキャッチする理由です。Pythonは各exceptを上から下にチェックし、最初のマッチで停止するため、特定な前に一般的なものを順序付けます:最初に配置された広い句がすべてをキャッチし、下の狭いものは決して実行しません。try/exceptがバグを隠さないようにする規律:最も狭い型をキャッチ。try本体を1行に保ちます。それは実際に発生できます。そして残りのすべてを伝播させます。20行の周りのラップされたtryは1つの期待された失敗を、19の予期しない失敗の上のマスクに変わります。

python
try:
    value = int("abc")
except ValueError:
    print("これは有効な番号ではありません")

キャッチする例外について具体的にしてください。すべての例外を裸のexcept:でキャッチすることはバグを隠します:

python
# 悪い。プログラマーの間違いを含め、すべてをキャッチ
try:
    result = do_something()
except:
    pass

# 良い。期待して、実際に処理できるものだけをキャッチ
try:
    result = do_something()
except FileNotFoundError:
    print("ファイルが見つかりません")
Junotry / except 失敗する可能性のあるコードをtryブロックに入れ、マッチするexceptがプログラムをクラッシュの代わりに実行します。ValueErrorのような期待する例外の名前を付けてください。すべてをキャッチする裸のexcept:ではなく。実際に対処できるものをキャッチし、残りを表示させます。
Junotry / excepttry/exceptは名前付き型をキャッチして回復。クラッシュしません。as eはメッセージを提供します。処理できる特定の型をキャッチするので、関連のないバグは表示されたままです。try本体を小さく保ちます。20行が1つの期待される失敗を、残りの上のマスクに変わります。
Junotry / except `except`は型を、そのすべてのサブタイプを含めマッチします。Pythonは最初の句を最初に取ります。マッチしたら、だから特定な前に一般的なものを順序付けます。最も狭い型をキャッチし、`try`を行に保ち、発生できます。そして残りのすべてを伝播させます。広い`try`はあなたが処理するつもりだった失敗より遠くに隠れます。

複数の例外をキャッチする

異なるエラー型を別々のexceptブロックで処理したり、タプルを使用して1つのブロックで複数の型をキャッチできます。as e部分はエラーメッセージへのアクセスを提供します。

複数のexcept句を異なる型でスタックし、Pythonはそれらを上から下にチェックして、最初のマッチを取ります。複数の型を同じ方法で処理するには、タプルでグループ化してください:except (ValueError, ZeroDivisionError)as eは例外をバインドするので、そのメッセージを読むことができます。順序は重要です:特定の型を一般的なものより前に配置するか。一般的な句が上に置かれると、ValueError句は決して実行しないデッドコードです。

順序はトラップです。Pythonは最初のexceptを取ります。その型がマッチし、広い型はその狭い親戚にマッチするため、except Exceptionexcept ValueErrorの上にリストしることはValueError句は決して実行しないデッドコードが、特定な最初。汎用最後。except (A, B) as eで応答を共有する型をグループ化してください。エラーをキャッチすると、コンテキストを追加して渡すだけの場合は、fromで新しいものを発生させます:raise ValueError("bad config") from e。これは元のエラーを新しいもの下の下に可視にしておくため、レポートは1つを別のもので置き換える代わりに、高レベルの意味と低レベルの原因の両方を表示します。

python
try:
    data = int(user_input)
    result = 100 / data
except ValueError:
    print("番号ではありません")
except ZeroDivisionError:
    print("ゼロで除算することはできません")

またはタプルで複数をキャッチ:

python
except (ValueError, ZeroDivisionError) as e:
    print(f"入力エラー:{e}")

as eは例外オブジェクトを名前にバインドするので、メッセージを検査できます。

Juno複数の例外をキャッチする 各エラー型に独自のexceptブロックを指定し、Pythonが最初のマッチを実行します。いくつかを同じ方法で処理するために、タプルでそれらをリストアップしてください:except (ValueError, ZeroDivisionError)as e部分はエラーオブジェクトを提供するので、そのメッセージを出力できます。
Juno複数の例外をキャッチする 複数のexcept句が上から下へ実行され、最初のマッチが勝ちます。だから広い前に特定な型をリストアップするか。広い句が狭いものを影で隠します。タプル。except (A, B)は1つのブロックで複数を処理します。as eは例外をバインドするので、そのメッセージを読むことができます。
Juno複数の例外をキャッチする 特定な句が最初に進みます:広い型が狭いもの上に置かれると、狭い句はデッドコードです。except (A, B) as eで共有応答をグループ化してください。再発生するとき、コンテキストを追加するには`raise NewError("...") from e`を使用するので、元の原因は、新しいエラー下で消える代わりに可視なままです。

else と finally

elseは例外が発生しなかった場合にのみ実行されます。finallyは常に実行されます。例外があるか否か関係なく。finallyは、結果に関わらず何が起ころうとも実行されなければならないクリーンアップに役立ちます。

elsetry本体が何も発生しなかった場合に実行されるコードを保持します。成功パス・コードをそれの外に保つことは意図を明確にします。あなたは、自分のexcept句の1つを偶然にトリガーしていない。finallyはクリーンアップの保証です。それが何であれ実行されます。成功の後。発生した後に。キャッチされた後に。未だにreturnの後でさえ。tryではで。だからfinallyは、結果に関わらずそれを行う必要があるリソースをリリースするのに適しています。

elsetry本体がクリーンに終了した場合にのみ実行されます。成功パス・コードをそれの外に保つので、自分のexcept句の1つを偶然にトリガーできません。finallyは無条件に実行されます:成功の後、キャッチされた例外の後、未だな後。tryでのでさえ。その最後のケースは知る価値のあるトラップを隠します:内のreturn finallytryからのreturnをオーバーライドし、もっと悪く、静かに伝播していた例外を飲み込みます。だからエラーは踏ん痕なく消えます。finallyをクリーンアップに保ちます。決してreturnをそれから。ファイルのために、withは既にこの保証を与えます。だからfinallyに達してください。主に、コンテキストマネージャを持たないリソースを保持しているとき。

python
try:
    with open("data.txt") as f:
        content = f.read()
except FileNotFoundError:
    print("ファイルが見つかりません。デフォルトを使用")
    content = ""
else:
    print("ファイルが正常に読み込まれました")
finally:
    print("ファイルの読み込み試行が完了しました")   # 常に実行

finallyはクリーンアップに最も役立ちます(接続をクローズ、ロックをリリース)。ファイルに既にwithを使用している場合でも。

Junoelse と finallyelseは`try`が何も発生しない場合にのみ実行されます。成功パスの残りのための整理された場所。finallyは常に実行されます。例外の有無。だから結果に関わらず何が起ころうとも実行される必要があるクリーンアップのためのスポット。ファイルで`with`は既にクリーンアップをカバーするので、あなたが予想するより`finally`に達することは少なくなります。
Junoelse と finallyelseはクリーン・パスで実行されます。成功コードをそれの外に保つので、自分の`except`をトリップできません。finallyは無条件に実行されます。`return`でも。だからあなたのクリーンアップの保証です。ファイルで`with`はこれを既に行うので、`finally`を保存してください。コンテキストマネージャなしでリソースのためのみ。
Junoelse と finallyelseはクリーン・パス・コード。それの外に保つので、自分の`except`句をトリップできません。finallyは何であれ実行されますが。決して`return`をそれから:これのオーバーライドは伝播する例外を飲み込み、エラーは静かに消えます。`finally`をクリーンアップに保ちます。そして主に`with`に寄りかかるものがないとき。

raise

raiseで自分自身の例外を発生させることができます。これはあなたのプログラムを呼び出し者に問題を明確に信号するために、間違った値を静かに返す代わりに機能させる方法です。

raise ExceptionType("message")は自分のコードから例外をスロー。これは関数が間違った値で行進する代わりに悪い入力を報告する方法です。exceptブロック内では、裸のraise(引数なし)はあなたがキャッチした例外を再スローして。ログに記録し、反応して、まだそれが上に移動させたいとき役立ちます。故意に発生させることは関数の失敗モードを作成します。その契約の一部。だから呼び出し者が名前でそれらをキャッチし、処理できます。

raise SomeError("message")は意図的に失敗を報告します。関数がそれを名誉できない入力を取得する場合、正しい移動:大きく拒否することは、後で謎として表面化する間違った答えを返すよりも優れています。except内では、裸のraiseはあなたがキャッチした例外を元のトレースバック無傷で再スローします。だから、ログと再スローできて、それがどこから来たか消えません。低レベルのエラーをドメイン1に変換したいとき、使用fromraise ConfigError("bad settings") from e元の下の新しい1の下に保つため、読み手は高レベルの意味と低レベルの原因の両方を見る代わりに1つを別のもので置き換える。経験則:コンテキストを追加するために再発生。決して隠さないために。

python
def divide(a, b):
    if b == 0:
        raise ValueError("ゼロで除算することはできません")
    return a / b

これはあなたの関数を期待し、問題を明確に呼び出し者に信号します。

Junoraiseraise ExceptionType("message")はあなたのコードが悪い値を続行する代わりに、問題を大きく旗立てさせます。関数がこれを言う方法「これで作業することはできません」だから呼び出し者がそれを扱います。明確で早いは、後で表示する間違った答えを打ちます。
Junoraiseraise ExceptionType("message")はあなたのコードから失敗を報告します。関数のエラーケースをどのように呼び出し者がそれを使用するかの部分にします。裸いraise `except`内で再スロー。あなたがキャッチしたもの。元のトレースバック無傷。だからログして、まだそれが上に移動させられます。
Junoraise 入力が名誉できないとき故意に発生させます:大きく拒否。間違った答えより後で謎として表面化。裸いraise元のトレースバック無傷で再スロー。低レベルのエラーをドメイン1に変換するには。`raise DomainError("...") from e`を使用するので、原因は可視なままです。新しいエラー下の代わりに消える。

カスタム例外クラス

より大きなプログラムのために、Exceptionから継承することで、自分の例外型を定義できます。これは呼び出し者が、他の種類のエラーから、あなたの特定のエラーを個別にキャッチさせます。

カスタム例外はあなた自身のExceptionから継承するクラスです(それは例外の新しい種類になります。だから同じ家族の木にスロットします)。報酬は呼び出し者が正確にキャッチできる名前です。組み込みエラーから別に。関連する失敗のグループのために。1つの基底クラスを作り、各特定なケースのためにそれをサブクラスにしてください。呼び出し者はグループ全体を処理するために基底をキャッチするか、1つを切り出すサブクラス。他の種類のエラーを散乱させずに。

Exceptionをサブクラスにしてください。BaseExceptionではない(Ctrl-Cとシャットダウンをカバーするルート。あなたはエラーをグループ化したくない)。自分の型を定義する理由。ValueErrorを再利用する代わりに。ファミリの木です:PaymentErrorのような基底を構築し、各モード(InsufficientFundsErrorCardDeclinedError)のためにそれをサブクラスにしてください。呼び出し者はPaymentErrorをキャッチして、全カテゴリを処理するか、1つのケースのサブクラス。メッセージ文字列を散乱させずに。クラスに__init__を与えてください。関連フィールドを搬送(アカウント。額)。だからハンドラは、テキストをスクレイピングする代わりに、コード内で何が起きたかを検査できます。これはエラーを、プログラムが作用できるものにします。プリントのみ。

python
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 -= amount
python
try:
    account.withdraw(1000)
except InsufficientFundsError as e:
    print(f"トランザクションが拒否されました:{e}")
Junoカスタム例外クラス `Exception`から継承することで、あなた自身のエラー型を作ります。そして単一の空のクラス本体は開始するのに十分です。これは呼び出し者にあなたのキャッチするための名前を与えます。組み込みエラーから別に。だからあなたのプログラムの問題は独立立ちます。
Junoカスタム例外クラス カスタム例外は`Exception`から継承するクラスです。呼び出し者に正確にキャッチするための名前を与えます。関連する失敗のために。1つの基底クラスを作り、ケース当たり1つのサブクラス:全グループのための基底をキャッチ。1つ。フィールドを追加して、メッセージ文字列を超えて詳細を搬送できます。
Junoカスタム例外クラス `Exception`をサブクラスにしてください。`BaseException`ではなく。だからあなたのエラーはCtrl-Cで塊にされません。あなたが自分の定義する理由。木です:`PaymentError`基底が特定なサブクラスで、呼び出し者は、メッセージテキストをスクレイピングせずに、カテゴリか1つのケースを処理できます。関連フィールドを`__init__`に置きます。だからハンドラはデータで作用します。文字列。

JSON

JSONはすべてが話す形式です:API。設定ファイル。データエクスポート。Pythonのjsonモジュールはそれを直接処理します。json.load()はファイルからJSONをPython辞書またはリストに読み込みます。json.dump()は辞書またはリストをファイルに戻してJSONを書き込みます。

ペアはそれらが触れるもので分けられます。json.load() / json.dump()はファイルオブジェクトで動作します。json.loads() / json.dumps()sを持つもの)はメモリ内の文字列で動作します。dump/dumpsindent=2を渡す。人間が出力を読むとき。それ以外は1行に出てくる。無効なJSONはjson.JSONDecodeErrorを発生させます。これはValueErrorの一種なので。ValueErrorをキャッチするハンドラは既にパース失敗をカバーします。

4つの名前は2つの操作。2つのソースで交差させます:load/dumpはファイル。loads/dumpsは文字列(sは「文字列」)。プロダクションで人々を引っかかる詳細は何がJSONは表現できません。それは日付、set。またはDecimalの概念を持ちません。だからjson.dumps(datetime.now())TypeErrorを発生させます。default=を渡すことで処理します。関数dump/dumpsは知らない任意の値で呼び出す。それはJSONが保持できるもの、通常str(value)を返すべきです。知る価値のある他の規則:数字はfloatとして往復します。だからあなたが正確さのためにDecimalとして書いた値はfloatとして戻り、それを失います。決して金またはその他の正確な小数が必要なもの(Numbers章を参照)。普通のJSON数として格納。

ファイルからJSONを読み込む:

python
import json

with open("config.json", "r") as f:
    config = json.load(f)    # JSONをPython辞書/リストに解析

print(config["setting"])

ファイルにJSONを書き込む:

python
import json

data = {"name": "太郎", "score": 87, "active": True}

with open("output.json", "w") as f:
    json.dump(data, f, indent=2)    # indent=は人間が読めるようにします

JSONからPython型へのマッピング:

JSONPython
object {}dict
array []list
string ""str
numberint または float
true / falseTrue / False
nullNone

ファイルを触らずにJSON文字列とPythonオブジェクトの間に変換する:

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を持つ)は文字列から読み込みます。

JunoJSONjson.load(f)ファイルのJSONをPython辞書とリストに変わります。`json.dump(data, f)`はそれらを戻し出力します。`s`バージョン。`json.loads`と`json.dumps`ファイルの代わりに文字列のために同じことをしてください。出力を読めるようにしたいときに`indent=2`を追加してください。
JunoJSON `load`/`dump`はファイルを処理します。`loads`/`dumps`は文字列を処理します。`s`は文字列です。`indent=2`は人間が読めるようにします。悪いJSONは`json.JSONDecodeError`を発生させます。これは`ValueError`なので。`ValueError`をキャッチするとパース失敗をカバーします。
JunoJSON 2つの操作は2つのソースで交差させます:`load`/`dump`はファイル。`loads`/`dumps`は文字列。JSONは日付。`set`。または`Decimal`を持ちません。だからそれらをダンプすることは、あなたが`default=`を渡さない限り`TypeError`を発生させます。そして数字は`float`として往復します。だから決して金をプレーンJSON数として格納。正確さを失うそれは帰路です。

実践で

小さなゲームの保存/読み込みパターン:状態をJSONに書き込み。次の実行時に読み込み。そして保存ファイルがまだ存在しない場合、デフォルトにフォールバック:

python
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)

設定ファイルを読み込み、結果を保存します。各失敗モードのための特定の例外処理付き:

python
import json

def load_config(path: str) -> dict:
    try:
        with open(path, "r") as f:
            return json.load(f)
    except FileNotFoundError:
        raise FileNotFoundError(f"設定ファイルが見つかりません:{path}")
    except json.JSONDecodeError as e:
        raise ValueError(f"{path}の無効なJSON:{e}")

def save_results(results: list[dict], path: str) -> None:
    with open(path, "w") as f:
        json.dump(results, f, indent=2)
    print(f"{len(results)}結果をsaved {path}に保存")

config = load_config("experiment.json")
results = [{"epoch": 1, "loss": 0.82}, {"epoch": 2, "loss": 0.61}]
save_results(results, "results.json")

タイムスタンプ付きエントリをファイルに追記する構造化ログライター。予期しない失敗を引っかかる最上位ハンドラ付き:

python
import json
from datetime import datetime

LOG_FILE = "run.log"

def log(level: str, message: str) -> None:
    ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    entry = f"[{ts}] [{level.upper():7}] {message}\n"
    with open(LOG_FILE, "a") as f:
        f.write(entry)

def process(config_path: str) -> None:
    log("info", f"ジョブを開始。設定:{config_path}")
    try:
        with open(config_path) as f:
            config = json.load(f)
        log("info", f"設定を読み込み:{config}")
    except FileNotFoundError:
        log("error", f"設定が見つかりません:{config_path}")
        raise
    except json.JSONDecodeError as e:
        log("error", f"設定のJSONが悪い:{e}")
        raise

try:
    process("config.json")
except Exception as e:
    log("critical", f"ジョブが失敗:{e}")

ログした後に再発生させると、元のトレースバックを呼び出し者のために保存します。最上位のexcept Exceptionはすべてを引っかかります。ログに滑った。そしてプロセスを明確に終了させます。