【问题标题】:Need to handle keyerror exception python需要处理keyerror异常python
【发布时间】:2012-11-16 09:13:00
【问题描述】:

当我在此处输入不在记录列表中的玩家姓名时,我遇到了 keyerror 异常。我可以搜索它并取回任何有效的名称,但如果我输入其他任何内容,我会收到一个 keyerror。我不太确定如何处理这个问题,因为它已经在处理通过解析我的文件创建的 3 组数据了。

我知道这段代码很糟糕,我是 python 新手,所以请原谅混乱 - 另请注意,这是一个让此功能正常工作的测试文件,然后我会将其写入我真正的主文件中的函数中。如果有任何意义的话,可以在这里做一个测试平台。

这是我的数据文件 stats4.txt 中的内容:

[00000] Cho'Gath - 12/16/3 - Loss - 2012-11-22
[00001] Fizz - 12/5/16 - Win - 2012-11-22
[00002] Caitlyn - 13/4/6 - Win - 2012-11-22
[00003] Sona - 4/5/9 - Loss - 2012-11-23
[00004] Sona - 2/1/20 - Win - 2012-11-23
[00005] Sona - 6/3/17 - Loss - 2012-11-23
[00006] Caitlyn - 14/2/16 - Win - 2012-11-24
[00007] Lux - 10/2/14 - Win - 2012-11-24
[00008] Sona - 8/1/22 - Win - 2012-11-27

这是我的代码:

import re

info = {}
records = []
search = []
with open('stats4.txt') as data:
    for line in data:
        gameid = [item.strip('[') for item in line.split(']')]
        del gameid[-1]
        gameidstr = ''.join(gameid)
        gameid = gameidstr
        line = line[7:]
        player, stats, outcome, date = [item.strip() for item in line.split('-', 3)]
        stats = dict(zip(('kills', 'deaths', 'assists'), map(int, stats.split('/'))))
        date = tuple(map(int, date.split('-')))
        info[player] = dict(zip(('gameid', 'player', 'stats', 'outcome', 'date'), (gameid, player, stats, outcome, date)))
        records.append(tuple((gameid, info[player])))

print "\n\n", info, "\n\n" #print the info dictionary just to see 
champ = raw_input() #get champion name
#print info[champ].get('stats').get('kills'), "\n\n"
#print "[%s] %s - %s/%s/%s - %s-%s-%s" % (info[champ].get('gameid'), champ, info[champ].get('stats').get('kills'), info[champ].get('stats').get('deaths'), info[champ].get('stats').get('assists'), info[champ].get('date')[0], info[champ].get('date')[1], info[champ].get('date')[2])
#print "\n\n"
#print info[champ].values()

i = 0
for item in records: #this prints out all records
    print "\n", "[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (records[i][0], records[i][1]['player'], records[i][1]['stats']['kills'], records[i][1]['stats']['deaths'], records[i][1]['stats']['assists'], records[i][1]['outcome'], records[i][1]['date'][0], records[i][1]['date'][1], records[i][1]['date'][2])
    i = i + 1

print "\n" + "*" * 50
i = 0
for item in records:
    if champ in records[i][1]['player']:
        search.append(records[i][1])
    else:
        pass
    i = i + 1

s = 0

if not search:
    print "no availble records" #how can I get this to print even if nothing is inputted in raw_input above for champ?


print "****"
for item in search:
        print "\n[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (search[s]['gameid'], search[s]['player'], search[s]['stats']['kills'], search[s]['stats']['deaths'], search[s]['stats']['assists'], search[s]['outcome'], search[s]['date'][0], search[s]['date'][1], search[s]['date'][2])
        s = s + 1

我尝试设置一个 Try;除了某种东西,但当输入无效的玩家名称时,我无法得到任何不同的结果。我想我可能可以用一个函数设置一些东西,如果名称存在或不存在,则返回不同的东西,但我想我只是让自己有点困惑。另请注意,对于不匹配的 8 条记录,确实不会打印任何匹配项,尽管这并不是我想要的工作方式。基本上我需要为任何无效的输入名称获取类似的东西,而不仅仅是一个恰好不在循环记录中的有效输入。

此数据的有效输入名称为: Cho'Gath、Fizz、Caitlyn、Sona 或 Lux - 其他任何东西都会给出关键错误,这就是我需要处理的内容,因此它不会引发错误,而只是打印类似“没有该英雄可用的记录”之类的内容(并打印只有一次,而不是 8 次)

感谢您的帮助!

[编辑] 我终于能够在帖子中更新此代码(感谢 martineau 将其添加进来,由于某种原因,反引号无法阻止代码,它显示为粗体普通文本当我粘贴时。无论如何,看看if not search,即使什么也没输入,我怎么能打印出来?只需在raw_input上按return,目前它会打印****之后的所有记录,即使我没有给它任何搜索冠军

【问题讨论】:

  • 反引号主要用于格式化小段代码,如this。要执行一段代码,请在粘贴之前或之后将每行缩进四个空格。或者,您可以将其全部粘贴为未缩进,然后将其全部选中并单击编辑窗口上方的{} 工具以对其进行格式化(在这种情况下意味着缩进)。
  • 啊,好吧,我知道这 4 个空格,但是对于 100 行左右的行来说这样做太乏味了,而且因为它在粘贴时会自动换行,所以会让人感到困惑,下次我会尝试记住 {}我相信这会更容易,感谢您修复我的帖子:)
  • 我要么在我的文本编辑器中进行缩进,这很容易,但在运行时往往会搞砸,或者在我描述的编辑窗口中。顺便说一句,我没有为您只是为您设置问题的格式,但不客气。

标签: python exception search dictionary


【解决方案1】:

您的确切错误发生在哪里?

我只是假设是champ = raw_input() #get champion name

然后info[champ]

您可以先检查密钥是否存在

if champ not in info:
  print 'no records avaialble'

或使用get

if info.get(champ)

或者您可以尝试访问密钥

try:
  info[champ] 
  # do stuff
except KeyError:
  print 'no records available'

您的问题越具体越好,尽管您解释了您的问题,但您确实没有包含任何细节如果可用,请始终包含追溯,并将相关代码发布在您的帖子中而不是链接上。

【讨论】:

  • 什么...由于某种原因它突然没有出现密钥错误,可能是在发布之前清理文件时我做了一些细微的改变,我会做更多的测试
  • 这似乎可以解决问题:i = 0 for item in records: if champ in records[i][1]['player']: search.append(records[i][1]) else: pass i = i + 1 print "no match" - 尽管无论如何这至少打印一次“不匹配”
  • @Kassandra 这是自学还是您正在参加的特定任务的课程?
  • @Jon 自学,我对这一切都很陌生,从来都不擅长,但决定再试一次 python
  • @dm03514 我想我现在需要做的是让它只打印一次“没有可用的记录”,并且只有在没有匹配的情况下
【解决方案2】:

以下是我认为可以解决您的问题的一些修改。我还重新格式化了代码以使其更具可读性。在 Python 中,可以通过以 \ 结尾的方式将长行继续到下一行,或者如果上一行有未配对的 '(' 或 '[' 则直接转到下一行。

另外,我将代码放入我的问题或答案的方式是从我的文本编辑器中将其剪切,然后将其粘贴到编辑窗口中,然后我确保它全部被选中,然后使用 {}编辑窗口顶部的工具来格式化它。

import re
from pprint import pprint

info = {}
records = []
with open('stats4.txt') as data:
    for line in data:
        gameid = [item.strip('[') for item in line.split(']')]
        del gameid[-1]
        gameidstr = ''.join(gameid)
        gameid = gameidstr
        line = line[7:]
        player, stats, outcome, date = [item.strip() for item in line.split('-', 3)]
        stats = dict(zip(('kills', 'deaths', 'assists'), map(int, stats.split('/'))))
        date = tuple(map(int, date.split('-')))
        info[player] = dict(zip(('gameid', 'player', 'stats', 'outcome', 'date'),
                                (gameid, player, stats, outcome, date)))
        records.append(tuple((gameid, info[player])))

#print "\n\n", info, "\n\n" #print the info dictionary just to see
pprint(info)
champ = raw_input("Champ's name: ") #get champion name
#print info[champ].get('stats').get('kills'), "\n\n"
#print "[%s] %s - %s/%s/%s - %s-%s-%s" % (
#       info[champ].get('gameid'), champ, info[champ].get('stats').get('kills'),
#       info[champ].get('stats').get('deaths'), info[champ].get('stats').get('assists'),
#       info[champ].get('date')[0], info[champ].get('date')[1],
#       info[champ].get('date')[2])
#print "\n\n"
#print info[champ].values()

i = 0
for item in records: #this prints out all records
    print "\n", "[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (
                 records[i][0], records[i][1]['player'], records[i][1]['stats']['kills'],
                 records[i][1]['stats']['deaths'], records[i][1]['stats']['assists'],
                 records[i][1]['outcome'], records[i][1]['date'][0],
                 records[i][1]['date'][1], records[i][1]['date'][2])
    i = i + 1

print "\n" + "*" * 50
i = 0
search = []
for item in records:
    if champ in records[i][1]['player']:
        search.append(records[i][1])
    i = i + 1
if not search:
    print "no match"
    exit()

s = 0
for item in search:
        print "\n[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (search[s]['gameid'],
              search[s]['player'], search[s]['stats']['kills'],
              search[s]['stats']['deaths'], search[s]['stats']['assists'],
              search[s]['outcome'], search[s]['date'][0], search[s]['date'][1],
              search[s]['date'][2])
        s = s + 1

【讨论】:

  • 非常感谢你,这似乎工作得很好:) 我已经看到了很多像你这里一样清晰对齐的代码,我只是不确定如何确保我的工作正常。如果用户没有为冠军名称输入任何内容,您的代码仍然会打印所有记录,但我找到了一个解决方案,方法是将搜索 if 语句更改为执行 if champ:<search append stuff>else: champ = "poop" 的较低语句,导致它只打印一次错误“不匹配”,因为 champ 无效(None 始终为 True,因为任何名称都是 > None,所以“”会将所有记录添加到搜索中,打印所有
  • 似乎您可以在raw_input() 之后使用if champ not in info:、print 'no match'、exit() 来检查champ。
  • 顺便说一句,您可以通过以下语句更轻松地获得gameid:import re、match = re.search(r'\[(\d+)\]', line),然后是gameid = match.group(1) if match else None。
  • 这也可以,但是我的方法遇到了一个小问题,我认为它也会影响它;我忽略了一点:如果我输入“l”,它匹配 Caitlyn,如果我输入“z”它匹配 Fizz,因为这些字母在这些名称中 - 有什么方法可以让 if champ in records[i][1]['player'] 只匹配完整匹配?我确信这不会是我的其他代码来验证你之前帮助我的冠军名称的问题,但是这里有什么方法可以处理吗?
  • 是的,我想知道那个验证码发生了什么。我想你需要if champ == records[i][1]['player']。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 2012-12-02
  • 1970-01-01
  • 2022-08-10
  • 1970-01-01
相关资源
最近更新 更多