ndb.get_multi返回AssertionError

时间:2015-08-20 01:57:38

标签: python python-2.7 google-app-engine google-cloud-datastore app-engine-ndb

在过去48小时左右,我的小python GAE应用程序已开始从ndb.get_multi调用中获取AssertionErrors。

附加完整的追溯,并且在/base / data /.../ndb/model.py的第734行的_BaseValue的__init__中生成服务器上生成错误,失败的断言是b_val不是None消息“无法包装无”

该错误似乎与特定实体或实体无关,但到目前为止我只看到过一种实体类型(尚未测试其他实体)。

get_multi调用仅适用于十几个键,并且错误是间歇性的,因此重复它有时会成功。或者不......

我没有通过远程shell看到这个错误,但我注意到我的本地安装是1.9.23,而日志条目说生产服务器是1.9.25(GoogleAppEngineLauncher说我的本地安装是最新的)

我正在添加一个解决方法来捕获异常并遍历密钥以单独获取它们但我仍然在context.py的第744行看到有关“暂停的生成器获取”的上游警告。

警告显示在列表中第一次获取此实体类型时,至少有2个不同的键列表(以及AssertionError之前)。

我不想以这种方式包装所有get_multi调用。

发生了什么事?

TRACEBACK:

Cannot wrap None
Traceback (most recent call last):
  File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/base/data/home/apps/s~thegapnetball/115.386356111937586421/handlers/assess.py", line 50, in get
    rs = ndb.get_multi(t.players)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 3905, in get_multi
    for future in get_multi_async(keys, **ctx_options)]
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 326, in get_result
    self.check_success()
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 372, in _help_tasklet_along
    value = gen.send(val)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 751, in get
    pbs = entity._to_pb(set_key=False).SerializePartialToString()
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 3147, in _to_pb
    prop._serialize(self, pb, projection=self._projection)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 2379, in _serialize
    projection=projection)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1405, in _serialize
    values = self._get_base_value_unwrapped_as_list(entity)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1175, in _get_base_value_unwrapped_as_list
    wrapped = self._get_base_value(entity)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1163, in _get_base_value
    return self._apply_to_values(entity, self._opt_call_to_base_type)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1335, in _apply_to_values
    value[:] = map(function, value)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1217, in _opt_call_to_base_type
    value = _BaseValue(self._call_to_base_type(value))
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 734, in \__init__
    assert b_val is not None, "Cannot wrap None"
AssertionError: Cannot wrap None

1 个答案:

答案 0 :(得分:6)

蒂姆霍夫曼和帕特里克科斯特洛让我走上正确的道路来解决这个问题。

我增加了版本以保护某些更改但是花费的时间比我预期的要长。

一个更改将重复的StructuredProperty添加到从ndb.Model派生的模型中,并且我将多个实体添加了额外的属性(总共约有1100个)。

没有额外属性的先前版本仍然是默认设置,并且被轻易使用,因此实体变得刚刚不足以产生间歇性断言错误。

主要教训是注意Google架构更新文章中的建议,特别是将基础父级更改为Expando和/或禁用数据存储区编辑,直到完成任何迁移。

https://cloud.google.com/appengine/articles/update_schema

修复方法是将属性添加到以前的版本,获取所有实体然后放入它们。

感谢Tim和Patrick的指针!