ProtocolBufferDecodeError:使用ndb.Key时被截断

时间:2013-10-23 06:20:35

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

我有这段代码,它曾经在升级GAE Python NDB之前工作:

class MyHandler(webapp2.RequestHandler):
  def get(self,urlString):
    resume = ndb.Key(urlsafe=urlString).get()

现在,我有这个错误:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1535, in __call__
    rv = self.handle_exception(request, response, e)
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1529, in __call__
    rv = self.router.dispatch(request, response)
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "C:\xampp\htdocs\mapjobs\main.py", line 127, in get
    resume_key = ndb.Key(urlsafe=urlString)
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\ndb\key.py", line 212, in __new__
    self.__reference = _ConstructReference(cls, **kwargs)
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\ndb\utils.py", line 136, in positional_wrapper
    return wrapped(*args, **kwds)
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\ndb\key.py", line 642, in _ConstructReference
    reference = _ReferenceFromSerialized(serialized)
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\ndb\key.py", line 774, in _ReferenceFromSerialized
    return entity_pb.Reference(serialized)
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\datastore\entity_pb.py", line 1791, in __init__
    if contents is not None: self.MergeFromString(contents)
  File "C:\Program Files (x86)\Google\google_appengine\google\net\proto\ProtocolBuffer.py", line 84, in MergeFromString
    self.MergePartialFromString(s)
  File "C:\Program Files (x86)\Google\google_appengine\google\net\proto\ProtocolBuffer.py", line 98, in MergePartialFromString
    self.TryMerge(d)
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\datastore\entity_pb.py", line 1920, in TryMerge
    d.skipData(tt)
  File "C:\Program Files (x86)\Google\google_appengine\google\net\proto\ProtocolBuffer.py", line 524, in skipData
    self.skip(4)
  File "C:\Program Files (x86)\Google\google_appengine\google\net\proto\ProtocolBuffer.py", line 499, in skip
    if self.idx + n > self.limit: raise ProtocolBufferDecodeError, "truncated"
ProtocolBufferDecodeError: truncated

亮点可能是:

File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2.py", line 570, in dispatch
  return method(*args, **kwargs)
File "C:\xampp\htdocs\mapjobs\main.py", line 127, in get
  resume_key = ndb.Key(urlsafe=urlString)

怎么了?

2 个答案:

答案 0 :(得分:3)

我的猜测是您通过Url参数接收密钥作为网址安全字符串,由于浏览器中的最大Url长度限制而被截断。实践中的浏览器将Url长度限制为最大2000个字符。请参阅此问题:What is the maximum length of a URL in different browsers?

如果您的密钥包含(多个)父密钥,则可以超过2000个字符。是这样的吗?请在创建和收到时检查urlsafe编码密钥的长度。

如果是这种情况,那么解决方法是仅使用实体的ID(或父键的实体)并手动构造密钥。

答案 1 :(得分:0)

我错配了以前的网址:

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/jobs',JobsHandler),
    ('/job/(.*)',JobHandler),
    ('/job/(.*)/update', JobUpdateHandler),
    ('/job/(.*)/delete', JobDeleteHandler),
    ('/job/create', JobCreateHandler),
    ('/resume/(.*)',ResumeHandler),
    ('/resume/(.*)/update', ResumeUpdateHandler),
    ('/resume/(.*)/delete', ResumeDeleteHandler),
    ('/resume/create', ResumeCreateHandler),
    ('/resumes',ResumesHandler),
    ('/profile',ProfileHandler),
    ('/profile/(.*)/update', ProfileUpdateHandler),
], debug=True)

请注意,我错误地排列了'/resume/(.*)',因为这应该位于底部以便最后接收urlString。这就是现在的情况:

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/jobs',JobsHandler),
    ('/job/(.*)/update', JobUpdateHandler),
    ('/job/(.*)/delete', JobDeleteHandler),
    ('/job/create', JobCreateHandler),
    ('/job/(.*)',JobHandler),
    ('/resume/(.*)/update', ResumeUpdateHandler),
    ('/resume/(.*)/delete', ResumeDeleteHandler),
    ('/resume/create', ResumeCreateHandler),
    ('/resume/(.*)',ResumeHandler),
    ('/resumes',ResumesHandler),
    ('/profile',ProfileHandler),
    ('/profile/(.*)/update', ProfileUpdateHandler),
], debug=True)