【发布时间】:2016-03-25 14:54:40
【问题描述】:
在生产环境中运行我的脚本时,我不断收到最奇怪的“KeyError”。这很奇怪,因为在开发中我没有收到任何错误。
我创建了一个“try-except”块来捕获错误,但字典似乎一切正常。没有钥匙丢失。这很奇怪,因为有时 for 循环会挂在它的中间,或者有时会抛出异常(即使它是完全相同的输入)。
我使用的是 Python 3.4,机器之间的区别是:
- 生产(AWS 的 EC2 微实例)仅使用 1 个 CPU (CPU0) 和 1GB RAM,并使用 3 个 Gunicorn 工人。
- 开发机器有 3 个 CPU(CPU0、CPU1、CPU2)、1 GB RAM 并使用 3 个 Guniorn 工作器(最多可有 9 个)。
以下是我的代码的过度简化。我的真实类有 26 个属性,其中两个接受动态生成的 HTML SVG 代码。字典列表的长度也可以是 0 到 100 之间的任何值(在开发中,我使用较小的字典列表(即 10)):
class myObject(object):
self.id = id
self.alias = alias
def get_me_objects(list_of_dicts):
try:
objects_list = []
print('Entering the faulty for loop...')
for i in range(len(list_of_dicts)):
id = list_of_dicts[i]['id']
alias = list_of_dicts[i]['alias']
obj = myObject(id, alias)
print('obj.id:' + str(print(obj.id)))
print('len(obj.__dict__):' + str(len(obj.__dict__)))
objects_list.append(obj)
except:
print('')
print('The following exception ocurred:')
e = sys.exc_info()[0]
print(e)
print('obj.id:' + str(obj.id))
print('len(obj.__dict__):' + str(len(obj.__dict__)))
print('obj.___dict__:' + str(obj.__dict__))
print('')
print('Returning objects_list')
print(objects_list)
return objects_list
当我用这个作为输入运行它时:
get_me_objects([{'id': 1009, 'alias': 'b'}, {'id': 8888, 'alias': 'c'}, {'id': 7778, 'alias': 't'}]
....它倾向于给我这个输出...
Entering the faulty for loop...
obj.id: 1009
len(obj.__dict__): 2
obj.id: 8888
len(obj.__dict__): 2
The following exception ocurred:
<class 'KeyError'>
obj.id: 8888
len(obj.__dict__): 2
obj.___dict__: {'alias': 'c', 'id': 8888}
Returning objects_list
[<app.views.my_scripts.MyObject object at 0x7f9c4c464198>, <<app.views.my_scripts.MyObject object at 0x7f9c4c46db38>]
...如果我再试一次,它有时可以给我这个输出(即使使用相同的字典列表!)...
Entering the faulty for loop...
...奇怪的是,如果我有时重试,它可以给我这个输出(即使是完全相同的字典列表!):
Entering the faulty for loop...
obj.id: 1009
len(obj.__dict__): 2
The following exception ocurred:
<class 'KeyError'>
obj.id: 1009
len(obj.__dict__): 2
obj.___dict__: {'alias': 'a', 'id': 1009}
Returning objects_list
[<app.views.my_scripts.MyObject object at 0x7f9c4c464198>]
所以我怀疑问题与 CPU 计算机电源有关。或者也许有一个问题存在于某个地方,我一生都看不到它。我还能做些什么来解决这个问题?
更新 1.0
Rob 提出了一个重要的观点,要求我删除 try-except 块以查看完整的回溯。我添加 try-except 块的原因是因为 Gunicorn 没有向我显示任何内容。一旦找到获取回溯的方法,我会立即更新我的帖子。
更新 2.0
按照 Rob 的建议,我检查了回溯(很明显!),发现有一个有效的 KeyError 来自另一个在 for 循环中调用的函数。它没有引起注意,因为首先,函数的名称用相似的变量名称伪装,其次,由于我不断从字典中得到“看似随机”的行为,我被严重分心了:
'In what order does python display dictionary keys?'):
顺序与它们在内部的工作方式以及它们在哈希表中的最终顺序有关。这又取决于键的哈希值、插入的顺序以及您使用的 Python 实现。
顺序是任意的(但不是随机的),知道它是什么顺序永远不会有用。
要获得排序后的键列表,只需使用 sorted(D),在您的情况下将返回 ['a', 'b', 'c']。
我的错。无论如何,谢谢大家的帮助!
【问题讨论】:
-
请不要捕获异常,而是显示整个回溯。您的异常消息没有帮助,因为它显示了上一次迭代中的
obj。 -
很公平,罗伯。我这样做是因为 Gunicorn 没有向我展示任何东西。让我看看我能做什么,我会更新我的帖子。
-
在访问“id”和“alias”字段之前,能否在“i”位置打印当前输入?
-
你可以使用 logger.exception 吗?它会自动进行回溯。
-
您的 keyerror 在字典中。使用 mydict = list_of_dict[i] 然后在 mydict 上进行 id 别名查找。当出现错误时,您将在 except 子句中查看有罪的字典。
标签: python amazon-ec2 python-3.4 keyerror