谷歌应用引擎-子类数据库.TextProperty用于将python字典存储为JSON并将默认编码设置为ASCII以外的



使用Google App Engine (python SDK),我创建了一个自定义JSONProperty()作为db.TextProperty()的子类。我的目标是动态地将python字典存储为JSON并方便地检索它。我遵循了通过谷歌找到的各种示例,设置自定义属性类和方法非常容易。

然而,我的一些字典值(字符串)是用utf-8编码的。当将模型保存到数据存储中时,我得到了一个可怕的Unicode错误(对于数据存储文本属性的默认编码是ASCII)。子类化数据库。BlobProperty没有解决问题。

基本上,我的代码做了以下事情:将资源实体存储到数据存储中(URL作为StringProperty, POST/GET有效负载作为JSONProperty存储在字典中),稍后获取它们(不包括代码)。我选择不使用pickle存储有效负载,因为我是一个JSON怪胎,没有使用存储对象。

Custom JSONProperty:

class JSONProperty(db.TextProperty):
    def get_value_for_datastore(self, model_instance):
        value = super(JSONProperty, self).get_value_for_datastore(model_instance)
        return json.dumps(value)
    def make_value_from_datastore(self, value):
        if value is None:
            return {}
        if isinstance(value, basestring):
            return json.loads(value)
        return value

将模型放入数据存储:

res = Resource()
res.init_payloads()
res.url = "http://www.somesite.com/someform/"
res.param = { 'name': "SomeField", 'default': u"éàôfoobarç" }
res.put()

这将抛出与ASCII编码相关的UnicodeDecodeError。也许值得注意的是,我只在生产服务器上(每次)得到这个错误。我在dev上使用python 2.5.2。

Traceback(最近一次调用):文件"/base/data/home/apps/delpythian/1.350065314722833389/core/handlers/ResetHandler.py",第68行,在_res_one返回res_one.put ()文件"/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/init.py",第984行返回datastore.Put(自我。_entity配置=配置)文件"/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py",第455行返回_GetConnection()。Async_put (config, entities, extra_hook).get_result()文件"/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py",第1219行,在async_put .py中PBS在pbsgen中:文件"/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py",第1070行,在__generate_pb_lists .py中Pb = value_to_pb(value)文件"/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py",第239行,在entity_to_pb .py中返回entity._ToPb ()文件"/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py",第841行,在_ToPb中属性= datastore_types。ToPropertyPb(名称、值)文件"/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore_type .py",第1672行,在ToPropertyPb .py中Pbvalue = pack_prop(name, v, pbb .mutable_value())文件"/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore_type .py",第1485行,在PackString中pbvalue.set_stringvalue (unicode(值).encode (utf - 8))UnicodeDecodeError: 'ascii'编解码器无法解码位置32的字节0xc3:序数不在范围(128)

我的问题是:有一种方法子类一个db.TextProperty()类和设置/强制自定义编码?还是我做错了什么?我尽量避免使用str(),并遵循"Decode early, Unicode everywhere, encode late"规则。

更新:添加代码和堆栈跟踪

下面是将unicode字符串从字典移动到序列化JSON字符串到TextProperty的最小示例:

class Thing(db.Model):
  json = db.TextProperty()
class MainHandler(webapp.RequestHandler):
  def get(self):
    data = {'word': u"rxe9sumxe9"}
    json = simplejson.dumps(data, ensure_ascii=False)
    Thing(json=json).put()

看行:PackString pbvalue.set_stringvalue(unicode(value).encode('utf-8')) UnicodeDecodeError: 'ascii'

似乎appengine期望所有字符串值都是unicode。调用unicode(value)没有指定编码,因此可能默认为ASCII,除非value已经是unicode,例如:

>>> u = u"ąęćźż"
>>> s = u.encode('utf-8')
>>> unicode(u) # fine
>>> unicode(s, 'utf-8') # fine
>>> unicode(s) # blows up (try's ascii) (on my interpreter)

json。转储将编码一个utf-8字符串(默认情况下),这就是为什么unicode不能处理它。

试试这个:

>>> return unicode(json.dumps(...), 'utf-8')

你会没事的。

至于为什么appengine崩溃而你的解释器很好,我的猜测是一些本地的设置,unicode的docstring表示它默认为当前的默认编码,对您来说显然是utf-8,对gae来说显然是ASCII。

最新更新