【问题标题】:Python throws random KeyError. Could it be lack of computational power?Python 抛出随机 KeyError。会不会是计算能力不足?
【发布时间】: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


【解决方案1】:

按照 Rob 的建议,我检查了回溯(呃!),发现有一个有效的 KeyError 来自另一个在 for 循环中被调用的函数。

这个错误没有被注意到(无论如何对我来说),因为首先,函数的名称被类似的变量名称伪装,其次,我期待在 Gunicorn 输出中看到回溯(但它没有发生),第三,由于我不断从字典中得到“看似随机”的行为,我严重分心。提醒:

'In what order does python display dictionary keys?'

顺序与它们在内部的工作方式以及它们在哈希表中的最终顺序有关。这又取决于键的哈希值、插入的顺序以及您使用的 Python 实现。

顺序是任意的(但不是随机的),知道它是什么顺序永远不会有用。

要获得排序后的键列表,只需使用 sorted(D),在您的情况下将返回 ['a', 'b', 'c']。

【讨论】:

    猜你喜欢
    • 2012-10-18
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    相关资源
    最近更新 更多