难以让ndb.tasklets在Google App Engine中运行

时间:2017-03-24 22:09:28

标签: python google-app-engine app-engine-ndb tasklet

我在使用Google App Engine的NDB数据存储区的异步API编写的一些tasklet中理解正在发生的事情时遇到了一些困难。概述是:我需要为用户汇总购买历史记录,“UserPurchase”对象引用已购买的“产品”或“自定义”项目,以及使用KeyProperty购买它的“建立”项目UserPurchase ndb.Model中的属性。我希望尽可能并行化各种NDB查找,因此我非常接近NDB文档(https://cloud.google.com/appengine/docs/standard/python/ndb/async)并构建了3个tasklet:

@ndb.tasklet
def get_establishment(purch):
    resto = yield purch.p_establishment.get_async()
    ret = {
        "rkey": resto.key.urlsafe(),
        "rname": resto.resto_name
    }
    raise ndb.Return(ret)

@ndb.tasklet
def get_item(purch):
    item = yield purch.p_item.get_async()
    if (purch.p_item.kind() == "Product"):
        ret = {
            "ikey": item.key.urlsafe(),
            "iname": item.name
        }
    else:
        ret = {
            "ikey": item.key.urlsafe(),
            "iname": item.cust_name
        }
    raise ndb.Return(ret)

@ndb.tasklet
def load_history(purch):
    at, item = yield get_establishment(purch), get_item(purch)
    ret = {
        "date": purch.p_datetime,
        "at_key": at.rkey,
        "at": at.rname,
        "item_key": item.ikey,
        "item": item.iname,
        "qty": purch.p_quantity,
        "type": purch.p_type
    }
    raise ndb.Return(ret)

然后,我这样打电话:

pq = UserPurchase.query().order(-UserPurchase.p_datetime)
phistory = pq.map(load_history, limit = 20)

检索最近显示的20件商品。然而,当我运行它时,我得到一个奇怪的例外,我不知道该怎么做...而且我对tasklet不够熟悉以及他们如何工作以自信地说我知道发生了什么。如果有人能给我一些关于寻找什么的指示,我真的很感激......!这是我运行上述代码时遇到的异常:

      ...
       File "/Programming/VirtualCellar/server/virtsom.py", line 2348, in get
        phistory = pq.map(load_history, limit = 20)
      File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/utils.py", line 160, in positional_wrapper
        return wrapped(*args, **kwds)
      File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/query.py", line 1190, in map
        **q_options).get_result()
      File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 383, in get_result
        self.check_success()
      File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 624, in _finish
        result = [r.get_result() for r in self._results]
      File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 383, in get_result
        self.check_success()
      File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 430, in _help_tasklet_along
        value = gen.send(val)
      File "/Programming/VirtualCellar/server/virtsom.py", line 2274, in load_history
        "at_key": at.rkey,
    AttributeError: 'dict' object has no attribute 'rkey'

根据错误,似乎tasklet不喜欢返回词典......

1 个答案:

答案 0 :(得分:1)

您错误地解释了错误消息:返回了一个dict,但您正在尝试访问该dict的一个不存在的属性。

您似乎想要访问里面的值,而不是dict的 atribute ,如果是,那么在load_history内更改:

        "at_key": at.rkey,

为:

        "at_key": at.get('rkey'),

或:

        "at_key": at['rkey'],

您还想重新审视您在atitem dicts中访问其他dict值的其他类似尝试。