• Arthur

Python KeyError异常以及如何处理它们

更新日期:5月 18

Python代写|CS代写|留学生程序代写



Python的KeyError异常是初学者遇到的常见异常。知道为什么KeyError可以提出a以及防止它停止程序的一些解决方案是改进Python程序员的重要步骤。

在本教程结束时,您将了解:

  • Python KeyError通常意味着什么

  • 您可能KeyError在标准库中看到的其他地方

  • KeyError看后如何处理

Python KeyError通常意味着什么

当您尝试访问不在字典()中的键时,将引发Python KeyError 异常dict

Python的官方文档说,KeyError当访问映射键并且在映射中找不到映射键时,引发。映射是将一组值映射到另一组的数据结构。Python中最常见的映射是字典。

Python KeyError是一种LookupError异常,表示检索您要查找的键时出现问题。当您看到时KeyError,语义含义是找不到正在寻找的密钥。

在下面的示例中,您可以看到ages定义了三个人年龄的字典()。当您尝试访问不在词典中的键时,将KeyError引发a:

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

在这里,试图访问关键'Michael'ages字典导致KeyError被提出。在回溯的底部,您将获得相关信息:

  • 一个事实KeyError升高

  • 找不到的钥匙是 'Michael'

倒数第二行告诉您哪一行引发了异常。从文件执行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.')

该代码将采用您在提示符下提供的名称,并尝试检索该人的年龄。在提示符下键入的任何内容都将用作ages第4行上字典的键。

从上面重复失败的示例,我们得到另一个回溯,这次回溯中包含有关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'

当您提供不在词典中的键时,程序将失败。在这里,回溯的最后几行指出了问题所在。File "ages.py", line 4, in <module>告诉您哪个文件的哪一行引发了所产生的KeyError异常。然后将显示该行。最后,KeyError异常提供了丢失的密钥。

因此,您可以看到KeyError回溯的最后一行本身并不能为您提供足够的信息,但是回溯之前的行可以使您更深入地了解问题出在哪里。

注意:与上面的示例一样,本教程中的其他大多数示例都使用f-strings,它们是Python 3.6中引入的。


您可能还会KeyError在标准库中看到Python 的地方

在大多数情况下,KeyError引发Python 是因为在字典或字典子类(例如os.environ)中找不到键。

在极少数情况下,zipfile如果在ZIP归档文件中找不到某项,则可能还会在Python标准库的其他地方(例如在模块中)看到它。但是,这些位置保留了与Python相同的语义KeyError,即找不到所需的密钥。

在以下示例中,您可以看到使用zipfile.ZipFile该类使用来提取有关ZIP存档的信息.getinfo()

>>>>>> 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: "There is no item named 'something' in the archive"

最后要注意的是,引发KeyError代码的行不在您的代码中。它在zipfile代码中,但是回溯的前几行指示代码中的哪些行导致了问题。


当您需要KeyError在自己的代码中引发Python 时

在某些情况下,您可能有必要在自己的代码中引发 Python KeyError异常。这可以通过使用raise关键字并调用KeyError异常来完成:

raise KeyError(message)

通常,message将是缺少的键。但是,与该zipfile软件包一样,您可以选择提供更多信息,以帮助下一个开发人员更好地了解问题所在。

如果您决定KeyError在自己的代码中引发Python ,只需确保您的用例与异常背后的语义匹配即可。它应该表示找不到正在寻找的密钥。

KeyError看到Python 时如何处理

当您遇到时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行显示了如何通过ages使用获得年龄值.get()。在这种情况下age,这将导致变量具有在字典中找到的所提供密钥的年龄值或默认值None

这次,您不会KeyError因为使用更安全的.get()方法来获取年龄而不是尝试直接访问密钥而引发异常:

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

在上面的示例执行中,KeyError当提供错误密钥时,不再引发。'Michael'在字典中找不到键,但是通过使用键.get(),我们得到的是None返回键,而不是凸起的键KeyError

age变量将具有在词典中找到的人的年龄或默认值(None默认情况下)。您还可以.get()通过传递第二个参数在调用中指定其他默认值。

这是上例中的第5行,使用以下命令指定了不同的默认年龄.get()

age = ages.get(person, 0)

在这里,它不是'Michael'返回而是返回None0因为找不到密钥,并且返回的默认值是now 0

罕见的解决方案:检查密钥

有时您需要确定字典中是否存在键。在这些情况下,使用.get()可能无法为您提供正确的信息。得到一个None从调用返回.get()可能意味着,关键是没有找到或价值发现在字典中的关键实际上是None

对于字典或类似字典的对象,可以使用in运算符来确定键是否在映射中。此运算符将返回一个布尔值(TrueFalse),指示是否在字典中找到该键。

在此示例中,您将response通过调用API 获得字典。该响应可能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在正常情况下加a,则备份用例将打印不同的消息。

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


结论

现在,您知道了KeyError可能引发Python 异常的一些常见地方,以及可以用来阻止它们停止程序的出色解决方案。

现在,下次看到KeyError凸起时,您将知道它可能只是错误的字典键查找。通过查看回溯的最后几行,您还将能够找到确定错误来源的所有必要信息。

如果问题是在您自己的代码中查找字典键,则可以从直接在字典上访问键切换为使用.get()具有默认返回值的更安全的方法。如果问题不是由您自己的代码引起的,那么使用代码try except块是控制代码流的最佳选择。

例外不必太可怕。一旦您知道如何理解其回溯中提供给您的信息以及异常的根本原因,那么您就可以使用这些解决方案使您的程序更可预测地运行。


7 次瀏覽