【问题标题】:Mysterious behavior in try-except-finallytry-except-finally 中的神秘行为
【发布时间】:2012-02-08 05:11:43
【问题描述】:

请原谅这个模糊的标题,我不知道该怎么说。

我有一个任务工作者请求处理程序,它从 URL 获取数据并将其写入 blobstore,并将数据的 blob_key 保存到数据存储中的 ListProperty。为了清楚起见,我试图简化代码:

class Fetch(webapp2.RequestHandler):
    def get(self):

        url = self.request.get('url')
        itemKey = self.request.get('itemKey')
        item = MyModel.get(itemKey)

        try:
            result = urlfetch.fetch(url=url)
            if result.status_code == 200:
                saveDataResult = save_data(result.content, itemKey)
                if saveDataResult is False:
                    raise Exception('error saving data')
            else:
                raise Exception('error fetching data: %s' % result.status_code)

            item.status = 'success'
        except Exception:
            item.status = 'failed'
        finally:
            item.put()

def save_data(data, itemKey)
    try:
        #write data to blobstore and get its blob_key...
        blob_key = files.blobstore.get_blob_key(file_name)
        item = MyModel.get(itemKey)
        item.blobKey.append(blob_key)
        item.put()

        return True
    except:
        return False

现在我遇到的问题是,当 saveDataResult 返回 True 时,它​​的状态设置为“成功”,但它的 blobKey 属性不包含任何值,即使生成了 blob_key 并且数据已成功写入。我看不出是什么原因导致这挽救了我的生命,请帮忙。

【问题讨论】:

  • 您还没有显示blob_key(不是item.blobKey)获得值的部分......或者这可能是问题所在?
  • 我已经添加了它,但我不能这样做,因为如果无法获取 blob_key,save_data 将返回 False。我很确定这不是原因。

标签: python google-app-engine google-cloud-datastore blobstore


【解决方案1】:

如果没有更多信息,很难确定发生了什么。这是我有根据的猜测:

MyModel.get(itemKey)get()save_data() 中都被调用。我推测它返回了代表该项目的两个不同对象。当 blobKey 在save_data 中更新时,更新仅发生在save_data 中获取的对象中。当您稍后在该范围之外检查它时,您看到的是另一个对象。

这是否正确取决于MyModel.get()的实现。

另外,你确实意识到你打电话给item.put() 两次,对吧?

【讨论】:

  • 所以我想我应该将项目的实例从 get() 传递给 save_data 作为参数?我现在正在尝试。
【解决方案2】:

问题来了

finally:
    item.put()

这个单一的调用会覆盖save_data() 保存的数据,因为它引用了一个旧的项目对象。

我的建议是您从save_data()item.status = 'success' 进行状态更新 或将item = MyModel.get(itemKey) 移动到save_data() 之后,以便获取更新后的对象。

【讨论】:

    【解决方案3】:

    问题是当你用item = MyModel.get(itemKey) 调用save_data() 再次从 Fetch 类中调用它,您最终会拥有两个不同的对象,因此会覆盖 save_data() 中的一个,因此当您转到模型数据存储时,不会将 blobkey 的数据存储为被覆盖的对象。

    尝试在课堂上做所有事情,否则你不要使用 item = MyModel.get(itemKey) 两次。

    【讨论】: