Python KeyError例外とそれらの処理方法

Python KeyError例外とそれらの処理方法

Pythonの `+ KeyError `例外は、初心者が遭遇する一般的な例外です。 ` KeyError +`が発生する理由と、プログラムがプログラムを停止させないようにするいくつかの解決策を知ることは、Pythonプログラマーとして改善するための重要なステップです。

このチュートリアルの終わりまでに、次のことがわかります:

  • Pythonの `+ KeyError +`が通常意味すること

  • 標準ライブラリで他に「+ KeyError +」が表示される場合

  • 見たときに `+ KeyError +`を処理する方法

*無料ボーナス:*リンク:[ここをクリックして無料のPythonチートシートを入手してください]データ型、辞書、リスト、Python関数の操作など、Python 3の基本を示します。

Pythonの `+ KeyError +`の通常の意味

Pythonの + KeyError + exceptionは、https://realpython.com/python-dicts/にないキーにアクセスしようとすると発生します[辞書]( + dict +)。

Pythonのhttps://docs.python.org/3/library/exceptions.html#KeyError [公式ドキュメント]は、マッピングキーにアクセスしたときに `+ KeyError +`が発生し、マッピングに見つからないと述べています。 マッピングは、1つの値セットを別の値セットにマップするデータ構造です。 Pythonで最も一般的なマッピングは辞書です。

Pythonの + KeyError +`はhttps://docs.python.org/3/library/exceptions.html#LookupError [+ LookupError `]例外の一種であり、探しているキーの取得に問題があったことを示します。 ` KeyError +`が表示された場合、意味的な意味は、検索されているキーが見つからなかったことです。

以下の例では、3人の年齢で定義された辞書( + ages +)を見ることができます。 辞書にないキーにアクセスしようとすると、 `+ KeyError +`が発生します:

>>>

>>> ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
>>> ages['Michael']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Michael'

ここでは、 `+ ages `辞書の ` 'Michael' `キーにアクセスしようとすると、 ` KeyError +`が発生します。 トレースバックの下部で、関連情報を取得します。

  • `+ KeyError +`が発生したという事実

  • 見つからなかったキーは、「+ 'Michael' +」でした

最後から2番目の行は、どの行で例外が発生したかを示しています。 この情報は、ファイルからPythonコードを実行する場合に役立ちます。

注意: Pythonで例外が発生すると、 traceback で処理されます。 トレースバックを使用すると、すべての関連情報が得られ、例外が発生した理由とその原因を特定できます。

Pythonトレースバックの読み方を学び、それがあなたに何を伝えているかを理解することは、Pythonプログラマーとして改善するために重要です。

以下のプログラムでは、再度定義された `+ ages +`辞書を見ることができます。 今回は、次の年齢を取得する人の名前を入力するよう求められます。

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5 print(f'{person} is {ages[person]} years old.')

このコードは、プロンプトで指定した名前を使用して、その人の年齢を取得しようとします。 プロンプトで入力した内容はすべて、4行目の `+ ages +`辞書のキーとして使用されます。

上記の失敗した例を繰り返して、別のトレースバックを取得します。今回は、 `+ KeyError +`が発生したファイル内の行に関する情報が含まれています。

$ python ages.py
Get age for: Michael
Traceback (most recent call last):
File "ages.py", line 4, in <module>
  print(f'{person} is {ages[person]} years old.')
KeyError: 'Michael'

辞書にないキーを指定すると、プログラムは失敗します。 ここで、トレースバックの最後の数行は問題を示しています。 <module> + + File "ages.py"、4行目は、どのファイルのどの行が結果の `+ KeyError `例外を発生させたかを示しています。 次に、その行が表示されます。 最後に、 ` KeyError +`例外は欠落しているキーを提供します。

したがって、 `+ KeyError +`トレースバックの最終行では、それだけでは十分な情報が得られないことがわかりますが、それより前の行を使用すると、何が問題なのかをより深く理解できます。

*注意:*上記の例のように、このチュートリアルの他の例のほとんどは、Python 3.6で導入されたhttps://realpython.com/python-f-strings/[f-strings]を使用します。

標準ライブラリでPythonの `+ KeyError +`が表示される可能性のある場所

ほとんどの場合、Pythonの `+ KeyError `は、キーが辞書または辞書サブクラス( ` os.environ +`など)で見つからないために発生します。

まれに、ZIPアーカイブでアイテムが見つからない場合、 `+ zipfile `モジュールなど、Pythonの標準ライブラリの他の場所で発生することもあります。 ただし、これらの場所はPythonの ` KeyError +`と同じセマンティックな意味を保持しますが、これは要求されたキーを見つけられません。

次の例では、 `+ .getinfo()`を使用して、ZIPアーカイブに関する情報を抽出するために ` zipfile.ZipFile +`クラスを使用していることがわかります。

>>>

>>> from zipfile import ZipFile
>>> zip_file = ZipFile('the_zip_file.zip')
>>> zip_file.getinfo('something')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/python/installation/zipfile.py", line 1304, in getinfo
  'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'something' in the archive"

これは実際には辞書キー検索のようには見えません。 代わりに、例外を発生させるのは `+ zipfile.ZipFile.getinfo()+`の呼び出しです。

トレースバックは、不足しているキーよりも少し多くの情報が与えられているため、少し異なります。

ここで最後に注意すべきことは、 `+ KeyError `を発生させた行がコードにないことです。 これは ` zipfile +`コードにありますが、トレースバックの前の行は、コードのどの行が問題を引き起こしたかを示しています。

独自のコードでPython `+ KeyError +`を発生させる必要がある場合

https://realpython.com/python-exceptions/#raising-an-exception [レイズする] Pythonの `+ KeyError `例外を独自のコードで意味がある場合があります。 これは、 ` raise `キーワードを使用して ` KeyError +`例外を呼び出すことで実行できます。

raise KeyError(message)

通常、 `+ message `が見つからないキーになります。 しかし、 ` zipfile +`パッケージの場合のように、次の開発者が何が問題なのかをよりよく理解できるように、もう少し情報を提供することもできます。

独自のコードでPythonの `+ KeyError +`を発生させる場合は、ユースケースが例外の背後にあるセマンティックの意味と一致することを確認してください。 探しているキーが見つからなかったことを示す必要があります。

Pythonの `+ KeyError +`を表示したときに処理する方法

`+ KeyError `が発生した場合、それを処理する標準的な方法がいくつかあります。 ユースケースによっては、これらのソリューションのいくつかは他のソリューションよりも優れている場合があります。 最終的な目標は、予期しない ` KeyError +`例外の発生を止めることです。

通常のソリューション: + .get()+

独自のコードで失敗した辞書キーのルックアップから `+ KeyError `が発生した場合、 ` .get()+`を使用して、指定されたキーで見つかった値またはデフォルト値を返すことができます。

前の年齢検索の例と同様に、次の例は、プロンプトで提供されるキーを使用して辞書から年齢を取得するより良い方法を示しています。

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5 age = ages.get(person)
 6
 7 if age:
 8     print(f'{person} is {age} years old.')
 9 else:
10     print(f"{person}'s age is unknown.")

ここで、5行目は、 `+ .get()`を使用して ` ages `から年齢の値を取得する方法を示しています。 これにより、指定されたキーのディクショナリで見つかった年齢の値またはデフォルト値、この場合は「 None 」を持つ「 age +」変数が作成されます。

今回は、キーに直接アクセスするのではなく、より安全な `+ .get()`メソッドを使用して年齢を取得するため、 ` KeyError +`例外は発生しません。

$ python ages.py
Get age for: Michael
Michael's age is unknown.

上記の実行例では、不正なキーが提供されたときに `+ KeyError `は発生しなくなりました。 キー ` 'Michael' `は辞書にありませんが、 ` .get()`を使用することで、発生した ` KeyError `ではなく ` None +`が返されます。

+ age +`変数には、辞書で見つかった人の年齢かデフォルト値(デフォルトでは `+ None +)があります。 2番目の引数を渡すことで、 `+ .get()+`呼び出しで別のデフォルト値を指定することもできます。

これは、上記の例の5行目であり、 `+ .get()+`を使用して指定された異なるデフォルトの年齢です:

age = ages.get(person, 0)

ここでは、 `+ 'Michael' `が ` None `を返す代わりに、キーが見つからないため ` 0 `を返し、返すデフォルト値は ` 0 +`になります。

まれな解決策:キーの確認

辞書内のキーの存在を判断する必要がある場合があります。 これらの場合、 `+ .get()`を使用しても正しい情報が得られない場合があります。 「 .get()」の呼び出しから返される「 None 」を取得すると、キーが見つからなかったか、辞書のキーで見つかった値が実際には「 None +」である可能性があります。

辞書または辞書のようなオブジェクトでは、 + in +`演算子を使用して、キーがマッピング内にあるかどうかを判断できます。 この演算子は、キーが辞書にあるかどうかを示すブール値( `+ True +`または `+ False +)を返します。

この例では、APIの呼び出しから `+ response `辞書を取得しています。 この応答には、応答に「 error +」キー値が定義されている場合があります。これは、応答がエラー状態にあることを示します。

 1 # parse_api_response.py
 2 ...
 3 # Assuming you got a `response` from calling an API that might
 4 # have an error key in the `response` if something went wrong
 5
 6 if 'error' in response:
 7     ...  # Parse the error state
 8 else:
 9     ...  # Parse the success state

ここでは、 `+ error `キーが ` response +`に存在するかどうかを確認し、キーからデフォルト値を取得することに違いがあります。 これは、実際に探しているのはキーが辞書にあるかどうかであり、そのキーの値ではないというまれなケースです。

一般的な解決策: + try + + except +

他の例外と同様に、 `+ try `ブロックと ` except +`ブロックを使用して、潜在的な例外発生コードを分離し、バックアップソリューションを提供できます。

以前と同様の例で `+ try `と ` except `ブロックを使用できますが、今回は通常の場合に ` KeyError +`が発生する場合に出力されるデフォルトのメッセージを提供します。

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5
 6 try:
 7     print(f'{person} is {ages[person]} years old.')
 8 except KeyError:
 9     print(f"{person}'s age is unknown.")

ここでは、人の名前と年齢を印刷する「+ try 」ブロックで通常のケースを見ることができます。 バックアップケースは ` except `ブロックにあり、通常のケースで ` KeyError +`が発生した場合、バックアップケースは別のメッセージを出力します。

+ try + `+ except `ブロックソリューションは、 ` .get()`または ` in `演算子をサポートしていない可能性がある他の場所にも最適なソリューションです。 ` KeyError +`が他の人のコードから発生している場合にも最適なソリューションです。

以下は、 `+ zipfile `パッケージを再度使用した例です。 今回は、 ` try `ブロックと ` except `ブロックを使用して、 ` KeyError +`例外がプログラムを停止しないようにします。

>>>

>>> from zipfile import ZipFile
>>> zip = ZipFile('the_zip_file.zip')
>>> try:
...     zip.getinfo('something')
... except KeyError:
...     print('Can not find "something"')
...
Can not find "something"

辞書のように + ZipFile +`クラスは `+ .get()+`を提供しないため、 `+ try + `+ except `ソリューションを使用する必要があります。 この例では、 ` .getinfo()+`に渡すのに有効な値を事前に知る必要はありません。

結論

Pythonの `+ KeyError +`例外が発生する可能性のある一般的な場所と、プログラムの停止を防ぐために使用できるいくつかの優れたソリューションがわかりました。

これで、次回 `+ KeyError +`が発生したとき、おそらく辞書キーの検索が不適切であることがわかります。 また、トレースバックの最後の数行を調べることで、エラーの原因を特定するために必要なすべての情報を見つけることができます。

問題が独自のコードでのディクショナリキールックアップである場合、ディクショナリ上のキーへの直接アクセスから、デフォルトの戻り値でより安全な `+ .get()`メソッドの使用に切り替えることができます。 問題が自分のコードに起因していない場合、コードのフローを制御するには、「 try 」「 except +」ブロックを使用するのが最善の策です。

例外は怖い必要はありません。 トレースバックで提供された情報と例外の根本原因を理解する方法がわかったら、これらのソリューションを使用して、プログラムの流れをより予測可能にすることができます。